IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue2学习笔记 -> 正文阅读

[JavaScript知识库]Vue2学习笔记

学习Vue2
看这个视频学的:
https://www.bilibili.com/video/BV1Zy4y1K7SH

入门小案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./js/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <!--创建一个容器-->
    <div id="root">
        <h1>hello,{{name}}</h1>
    </div>
    <script>
        //创建一个Vue实例
        new Vue({
            el:'#root',	//指定哪个容器,这里用了id选择器
            data:{
                name:'friend'
            }
        })
    </script>
</body>
</html>

1个容器只能对应1个Vue实例

{{xx}}两个花括号里面的内容xx可以是js表达式,如:1+1,Date.now()等

模板语法

模板语法有下面两种:

  • 双花括号的是插值语法
  • 指令语法
<body>
    <div id="root">
        <h1>hello,{{name}}</h1>
        <!-- v-bind:可以简写为: 
        :href='xxx',xxx也可以写js表达式如school.url.toUpperCase()
        -->
        <a v-bind:href="school.url">链接</a> 
        <a :href="school.url">链接</a>    
    </div>

    <script>
        new Vue({ 
            el:'#root',
            data:{
                name:'friend',
                school:{
                    url:'http://www.baidu.com'
                }
            }
        })
    </script>
</body>

开始标签与结束标签之间的内容用{{xx}},标签里面的属性用指令语法

数据绑定

2种数据绑定的方式:

  • 单向绑定:数据只能从Vue实例里面的data传到页面
  • 双向绑定:数据不仅能从Vue实例里面的data传到页面,还可以从页面传到Vue实例里面的data。使用v-model:
<body>
    <div id="root">
       <input v-model:value="name">
    </div>

    <script>
        new Vue({ 
            el:'#root',
            data:{
                name:'friend',
            }
        })
    </script>
</body>

在这里插入图片描述

这里我在输入框输入123,vue开发者工具可以看到也自动变化了。

双向绑定一般使用在表单输入类标签上如<input>,<select>等。v-model:value可以简写为v-model,因为v-model默认的就是标签的value值。

el和data的两种写法:

<script>
        new Vue({ 
            el:'#root',		//el的第1种写法
            data:{			//data的第1种写法
                name:'friend'
            }
        })
    </script>
<script>
        const v = new Vue({
            data:function(){	//data的第2种写法,这里不可以写为箭头函数的形式!
                return{
                   name:'friend' 
                }
            }
        });
        v.$mount('#root');	//el的第2种写法
    </script>

MVVM模型

在这里插入图片描述

简单理解:

  • v就是指HTML页面
  • m就是Vue实例里data的数据
  • vm就是Vue实例

图里的DataBindings可以理解为把data的数据,绑定到HTML页面上(就像上面几个小节的例子)

DOM Listeners就是比如我们使用双向绑定的时候,在输入框输入数据,data的数据也会跟着变,就是它要一直监听我们的页面,它监听到我们在输入框输入了数据,那么它就做相应的处理去改变data里的数据。

在这里插入图片描述

官方文档里用vm代表Vue实例,就像这样:

const vm = new Vue({ 
            //el:'#root',
            data:{
                   name:'friend'
              }
        });

数据代理

在这里插入图片描述

修改number的值,person对象里的age属性也会跟着发生变化,但他不是通过person.age = number这种直接赋值的方式修改的,而是通过defineProerty()函数里的第3个参数进行配置,配置get()、set()函数来获取和修改person的age属性的。

这里的get()是简写,可以写为get:function(){…},set()也一样

//数据代理简单例子,通过1个对象代理,对另一个对象中的属性进行操作(读/写)
let obj1 = {x:100}
        let obj2 = {y:200}
        Object.defineProperty(obj2,'x',{
            get(){
                return obj1.x;
            },
            set(value){
                obj1.x = value;
            }
        })

在这里插入图片描述

没有直接修改obj1的x属性,而是通过修改obj2的x属性来实现修改obj1的x属性的。

Vue中的数据代理

在这里插入图片描述

事件处理

简单点击使用v-on

<body>
    <div id="root">
       <button v-on:click="showInfo($event,'321')">点我</button>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{},
            methods:{
                showInfo(event,num){
                    alert('你好呀'+num);
                }                               
            }
        });
    </script>
</body>

showInfo( e v e n t , ′ 32 1 ′ ) , event,'321'), event,321)event是点击的事件,如果不写出来的话函数里即使你写了showInfo(event,num)参数你也是接收不到的

在这里插入图片描述

事件修饰符

@click.xx xx就是修饰符

在这里插入图片描述

prevent

<body>
    <div id="root">
        <a href="http://www.baidu.com" @click='showInfo'>百度</a>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{},
            methods:{
                showInfo(){
                    alert('你好呀');
                }                               
            }
        });
    </script>
</body>

当我点击百度a标签时,会先执行showInfo()弹窗显示’你好呀’,当你关闭弹窗后,他会自动跳转到href属性的地址,也就是百度。如果不想他进行跳转,那就加个prevent修饰符阻止他的默认行为(即跳转页面)。

<a href="http://www.baidu.com" @click.prevent='showInfo'>百度</a>

stop

<div @click='showInfo1'>
        div1
        <div @click='showInfo2'>div2</div>
    </div>

像这种嵌套的情况,外层div有点击事件,内层div也有点击事件,那么当我点击div2时,就会先执行div2的点击事件showInfo2(),然后就冒泡上去,执行showInfo1的事件。如果想阻止冒泡的行为,在内层添加stop修饰符

<div @click='showInfo1'>
        div1
        <div @click.stop='showInfo2'>div2</div>
    </div>

once

比如1个按钮有点击事件,每点1次按钮就执行1次它的点击事件,但是我想只允许用户执行1次这个按钮的点击事件,后面无论点多少次都不执行这个按钮的点击事件了,这时就可以加once修饰符

<button @click.once='showInfo'>btn</button>

修饰符也可以连着用,如@click.prevent.stop,表示阻止默认行为并且停止冒泡

键盘事件

@keyup当按键弹起时,@keydown当按键按下时

<body>
    <div id="root">
        <input type="text" @keyup.enter='showInfo'>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{},
            methods:{
                showInfo(){
                    alert('你好呀');
                }                               
            }
        });
    </script>
</body>

@keyup.enter表示当按下回车键然后松手就执行事件

enter可以替换为其他按键:

在这里插入图片描述

如果想同时按下ctrl键和y键才执行事件,可以这样写:@keydown.ctrl.y

计算属性

<body>
    <div id="root">
        <input type="text" v-model="firstName"><br>
        <input type="text" v-model="lastName"><br>
        <span>{{fullName}}</span>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                firstName:"张",
                lastName:"三"
            },
            computed:{      //计算属性
                fullName:{
                    get(){
                        //此处的this指的是vm
                        return this.firstName+"-"+this.lastName;
                    },
                    set(value){
                        const arr = value.split('-');
                        this.firstName = arr[0];
                        this.lastName = arr[1];
                    }
                }
            }
        });
    </script>
</body>

在这里插入图片描述

在这里插入图片描述

简写方式

计算属性只是用来读取,不修改的情况下,才能简写

computed:{      //计算属性
	fullName:function(){
		//此处的this指的是vm
		return this.firstName+"-"+this.lastName;
	}
}

再简单点

computed:{      //计算属性
	fullName(){
		//此处的this指的是vm
		return this.firstName+"-"+this.lastName;
	}
}

监视属性

<body>
    <div id="root">
        <p>今天天气很{{info}}</p>
        <button @click="changeWeather">切换天气</button>
    </div>

    <script>
        const vm = new Vue({
            el:'#root',
            data:{
                isHot:true
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot;
                }
            },
            computed:{      //计算属性
                info(){
                        //此处的this指的是vm
                        return this.isHot ? '热':'冷'
                    }
            },
            watch:{     //监视属性
                isHot:{     //表示你要监视isHot属性
                    handler(newValue,oldValue){
                        console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
                    }
                }
            }
        });

        /*监视属性的另一种写法
        vm.$watch('isHot',{
             handler(newValue,oldValue){
             	console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
             }
        })
        */
    </script>
</body>

在这里插入图片描述

在这里插入图片描述

深度监视

<body>
    <div id="root">
        <p>今天天气很{{info}}</p>
        <button @click="changeWeather">切换天气</button>
    </div>

    <script>
        const vm = new Vue({
            el:'#root',
            data:{
                isHot:true,
                numbers:{
                    a:1,
                    b:2
                }
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot;
                }
            },
            computed:{      //计算属性
                info(){
                        //此处的this指的是vm
                        return this.isHot ? '热':'冷'
                    }
            },
            watch:{     //监视属性
                isHot:{     //表示你要监视isHot属性
                    handler(newValue,oldValue){
                        console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
                    }
                },
                //监视多级结构中的某个属性的变化
                /*'numbers.a':{   //注意这里一定要用引号包围键
                    handler(){
                        console.log("a被改了");
                    }
                },*/
                //监视多级结构中的多个属性的变化
                numbers:{
                    deep:true,
                    handler(){
                        console.log("a被改了");
                    }
                }
            }
        });
    </script>
</body>

在这里插入图片描述

简写方式

<body>
    <div id="root">
        <p>今天天气很{{info}}</p>
        <button @click="changeWeather">切换天气</button>
    </div>

    <script>
        const vm = new Vue({
            el:'#root',
            data:{
                isHot:true
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot;
                }
            },
            computed:{      //计算属性
                info(){
                        //此处的this指的是vm
                        return this.isHot ? '热':'冷'
                    }
            },
            watch:{     //监视属性
                //一般写法
                isHot:{     //表示你要监视isHot属性
                    //immediate:true,
                    //deep:true,
                    handler(newValue,oldValue){
                        console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
                    }
                },
                /*简写方法
                isHot(newValue,oldValue){
                    //这个函数就相当于handler()函数,这里函数名就是你要监视的属性名
                    console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
                }*/
            }
        });
        /*vm.$watch一般写法
        vm.$watch('isHot',{
            immediate:true,
            deep:true,
            handler(newValue,oldValue){
                console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
            }
        })
        */
       /*vm.$watch简单写法
        vm.$watch('isHot',(newValue,oldValue){
                console.log("isHot被修改","新的值"+newValue,"旧的值"+newValue)
            })
        */
    </script>
</body>

计算属性和监视属性的区别

在这里插入图片描述

绑定样式

绑定class样式方法1

<head>
    <script src="./js/vue.js"></script>
	<style>
        .normal{
            color: orange;
        }
    </style>
</head>
<body>
    <div id="root">
        <!-- 绑定样式方法1,字符串写法,适用于:样式的类名不确定,需要动态指定 -->
        <div class="basic" :class="mood">div</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                mood:'normal'
            }
        })
    </script>
</body>

绑定class样式方法2

<head>
    <script src="./js/vue.js"></script>
    <style>
        .normal{
            color: orange;
        }
        .boxborder{
            border: green 1px solid;
        }
    </style>
</head>
<body>
    <div id="root">
        <!-- 方法2,数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
        <div class="basic" :class="arr">方法2</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                arr:['normal','boxborder']
            }
        })
    </script>
</body>

绑定class样式方法3

<head>
    <script src="./js/vue.js"></script>
    <style>
        .normal{
            color: orange;
        }
        .boxborder{
            border: green 1px solid;
        }
    </style>
</head>
<body>
    <div id="root">
        <!-- 方法3,对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
        <div class="basic" :class="classObj">方法2</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                classObj:{
                    normal:true,	//true表示使用这个样式,false表示不用
                    boxborder:true
                }
            }
        })
    </script>
</body>

绑定style样式方法1

<body>
    <div id="root">
        <div class="basic" :style="styleObj">方法1</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                styleObj:{
                    fontSize:'40px'
                }
            }
        });
    </script>
</body>

绑定style样式方法2

<body>
    <div id="root">
        <div class="basic" :style="[styleObj1,styleObj2]">方法1</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                styleObj1:{
                    fontSize:'40px',
                    color:'green'
                },
                styleObj2:{
                    border:'blue 1px solid'
                }
            }
        });
    </script>
</body>

条件渲染

在这里插入图片描述

在这里插入图片描述

v-show其实就是控制标签的display:none属性,true就显示出来,false就隐藏(但是在浏览器上看DOM节点还在)

v-if true就显示出来,false就消除(在浏览器上看DOM节点不存在!

<template>标签与v-if配合使用,v-if为true时,在页面上是没有<template>标签的,直接把<template>标签里面的内容显示出来,当v-if为false时,整个<template>标签包括里面的内容都消失(在浏览器上看DOM节点也是不存在的)

列表渲染

在这里插入图片描述

遍历数组

<body>
    <div id="root">
        <ul>
            <!-- :key的值要是唯一的,所以这里取索引值index,其他的唯一值如p.id也可以 
            遍历数组
            -->
            <li v-for="(p,index) in persons" :key="index">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                persons:[
                    {id:'01',name:'tom',age:18},
                    {id:'02',name:'mike',age:19},
                    {id:'03',name:'tony',age:20}
            ]
            }
        });
    </script>
</body>

遍历对象

<body>
    <div id="root">
        <ul>
            <!-- 遍历对象-->
            <li v-for="(value,key) in car" :key="key">
                {{value}}-{{key}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                car:{
                    name:'波子',
                    price:'100W'
                }
            }
        });
    </script>
</body>

遍历字符串

<body>
    <div id="root">
        <ul>
            <!-- 遍历字符串-->
            <li v-for="(value,key) in str" :key="key">
                {{value}}-{{key}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                str:'hello'
            }
        });
    </script>
</body>

遍历指定次数

<ul>
    <!-- 遍历字符串-->
    <li v-for="(value,key) in 5" >
    <!-- 这里value从1开始,遍历5次即从1到5 -->
    {{value}}-{{key}}
    </li>
</ul>

key的原理

在这里插入图片描述

列表过滤

<body>
    <div id="root">
        <input type="text" v-model='keyword'>
        <ul>
            <li v-for="(p,key) in filterData" :key='p.id'>
                {{p.id}}-{{p.name}}-{{p.email}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                keyword:'',
                persons:[
                    {id:'001',name:'tony',email:'123@qq.com'},
                    {id:'002',name:'tom',email:'123@qq.com'},
                    {id:'003',name:'mike',email:'123@qq.com'}
                ]
            },
            computed:{
                filterData(){
                    return this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyword)!==-1;
                    });
                }
            }
        });
    </script>
</body>

在这里插入图片描述

在这里插入图片描述

就类似模糊查询

列表排序

<body>
    <div id="root">
        <input type="text" v-model='keyword'>
        <button @click="sortType=0">原顺序</button>
        <button @click="sortType=1">降序</button>
        <button @click="sortType=2">升序</button>
        <ul>
            <li v-for="(p,key) in filterData" :key='p.id'>
                {{p.id}}-{{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                keyword:'',
                sortType:0,//0原顺序,1降序,2升序
                persons:[
                    {id:'001',name:'tony',age:35},
                    {id:'002',name:'tom',age:33},
                    {id:'003',name:'mike',age:66}
                ]
            },
            computed:{
                filterData(){
                    let arr = this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyword)!==-1;
                    });
                    //判断是否需要排序
                    if(this.sortType){
                        arr.sort((p1,p2)=>{
                            return this.sortType == 1 ? p2.age-p1.age : p1.age-p2.age;
                        });
                    }
                    return arr;
                }
            }
        });
    </script>
</body>

数据监测

在这里插入图片描述

<body>
    <div id="root">
        <button @click="student.age++">年龄+1岁</button>
        <button @click="addSex">添加性别属性值,默认值:男</button>
        <button @click="student.sex= '未知' ">修改性别</button>
        <button @click="addFriend">在列表首位添加一个朋友</button>
        <button @click="updateFirstFriendName">修改第1个朋友的名字</button>
        <button @click="addHobby">添加一个爱好</button>
        <button @click="removeLearn">过滤掉爱好中的学习</button>
        <h3>姓名:{{student.name}}</h3>
        <h3>年龄:{{student.age}}</h3>
        <h3 v-show="student.sex">性别:{{student.sex}}</h3>
        <h3>爱好:</h3>
        <ul>
            <li v-for="(h,index) of student.hobby" :key="index">
                {{h}}
            </li>
        </ul>
        <h3>朋友:</h3>
        <ul>
            <li v-for="(f,index) of student.friends" :key="index">
                {{f.name}}--{{f.age}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                student:{
                    name:'tom',
                    age:18,
                    hobby:['跑步','打篮球'],
                    friends:[
                    {name:'tony',age:35},
                    {name:'tom',age:33},
                    {name:'mike',age:66}
                    ]
                }
            },
            methods:{
                addSex(){
                    //Vue.set(this,student,'sex','男'); //方法1
                    this.$set(this.student,'sex','男'); //方法2
                },
                addFriend(){
        
                    this.student.friends.unshift({name:'sarah',age:19});
                },
                updateFirstFriendName(){
                    this.student.friends[0].name = 'kk';
                },
                addHobby(){
                    this.student.hobby.push('学习')
                },
                updateHobby(){
                    //this.student.hobby.splice(0,1,'开车');    //方法1
                    //Vue.set(this.student.hobby,0,'开车');     //方法2
                    this.$set(this.student.hobby,0,'开车');     //方法3
                },
                removeLearn(){
                    this.student.hobby = this.student.hobby.filter((h)=>{
                        return h!== '学习';
                    });
                }
            }
        });
    </script>
</body>

收集表单数据

在这里插入图片描述

<body>
    <div id="root">
        <!-- @submit表单的提交事件,prevent阻止默认行为,即阻止表单点击提交后跳转页面 -->
        <form @submit.prevent="demoFunc">
            账号:<input type="text" v-model="userInfo.account"><br><br>
            密码:<input type="text" v-model="userInfo.password"><br><br>
            <!-- v-model.number作用:把输入值转为数字而不是字符串,如 age:30 而不是 age:'30' -->
            年龄:<input type="number" v-model.number="userInfo.age"><br><br>
            性别:
            <!-- 注意这里一定要加value --><input type="radio" name="sex" v-model="userInfo.sex" value="male"><input type="radio" name="sex" v-model="userInfo.sex" value="female"><br><br>
            爱好:
            学习<input type="checkbox" v-model="userInfo.hobby" value="study">
            打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
            <br><br>
            所在城市
            <select v-model="userInfo.city">
                <option value="">请选择城市</option>
                <option value="guangzhou">广州</option>
                <option value="shenzhen">深圳</option>
            </select>
            <br><br>
            补充信息:
            <textarea v-model="userInfo.other"></textarea><br><br>
            <input type="checkbox" v-model="userInfo.agree">阅读并接受。。。
            <button>提交</button>
        </form>
    </div>
    <script>
        new Vue({
            el:"#root",
            data:{
                userInfo:{
                    account:'',
                    password:'',
                    age:18,
                    sex:'male',
                    hobby:[],
                    city:'',
                    other:'',
                    agree:''
                }
            },
            methods: {
                demoFunc(){
                    console.log("发送");
                }
            }
        })
    </script>
</body>

过滤器

在这里插入图片描述

<body>
    <div id="root">
        <h3>现在的时间:{{Date.now()}}</h3>
        <!-- 用过滤器格式化时间 |为管道符-->
        <!-- 这里timeFormater不写括号默认把|左边的值作为参数传入 -->
        <h3>格式化后:{{Date.now() | timeFormater}}</h3>
        <h3>格式化后(有参数):{{Date.now() | timeFormater('YYYY年MM月DD日')}}</h3>
        <h3>格式化后(有参数):{{Date.now() | timeFormater('YYYY年MM月DD日') | mySlice}}</h3>
    </div>
    <script>
        //设置全局过滤器,表示即使有多个Vue实例都能共同使用
        //filter第1个参数为过滤器名,第2个参数为过滤器的函数部分
        Vue.filter('mySlice',function(value){   
            return value.slice(0,5);    //提取字符串,从第0个开始,到5之前
        });
        new Vue({
            el:"#root",
            data:{
                
            },
            filters:{   //这里都是局部过滤器,如果用另一个Vue实例是不能调用这些过滤器的
                //
                timeFormater(value,format="YYYY-MM-DD HH:mm:ss"){
                    return dayjs(value).format(format);
                }
            }
        })
    </script>
</body>

在这里插入图片描述

v-text

在这里插入图片描述

<body>
    <div id="root">
        <div v-text="name"></div>
    </div>
    <script>
        new Vue({
            el:"#root",
            data:{
                name:'jack'
            },
        })
    </script>
</body>

注意,如果这里的name包含html标签,如name=’<h3>hello</h3>’,vue是不会解析的,只会把整个’<h3>hello</h3>'当作字符串显示出来

v-html

这个指令就能把html标签也解析出来

<body>
    <div id="root">
        <div v-html="name"></div>
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                name:'<h1>321</h1>'
            },
        })
    </script>
</body>

在这里插入图片描述

v-cloak

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./js/vue.js"></script>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <div v-cloak>{{name}}</div>
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                name:'123'
            },
        })
    </script>
</body>

在这里插入图片描述

场景:网络很慢时,vue.js文件还没加载完,在页面上直接显示’{{name}}'这么个东西用户看起来感觉很怪,只有当vue.js加载完,{{name}}才会变为它的值123。

为了避免用户看起来感觉很怪可以配合css[v-cloak]{display: none;},这样即使vue.js文件还没加载完,页面上也不会出现{{name}}这个东西

v-once

在这里插入图片描述

<body>
    <div id="root">
        <div v-once>{{n}}</div>
        <div>{{n}}</div>
        <button @click="n++">点击n+1</button>
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                n:1
            },
        })
    </script>
</body>

v-once就是标签里的数据第一次渲染后就不会再变的了

v-pre

在这里插入图片描述

<body>
    <div id="root">
        <div v-pre>{{n}}</div>
        <div>{{n}}</div>
        <button @click="n++">点击n+1</button>
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                n:1
            },
        })
    </script>
</body>

在这里插入图片描述

把v-pre指令用在有Vue语法的标签里,那么这个标签里的内容Vue不会进行解析

自定义指令

<body>
    <div id="root">
        <div>{{n}}</div>
        <div >自定义指令数字放大10倍<span v-big="n"></span></div>
        <button @click="n++">点击n+1</button>
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                n:1
            },
            directives:{
                //函数何时被调用?
                //1.指令与元素成功绑定时(一打开页面)2.指令所在模板被重新解析时
                big(element,binding){
                    element.innerText=binding.value*10;
                }
            }
        })
    </script>
</body>

在这里插入图片描述

对象写法

<body>
    <div id="root">
        <div>{{n}}</div>
        <div >自定义指令数字放大10倍<span v-big="n"></span></div>
        <button @click="n++">点击n+1</button>
        <input v-fbind:value="n">
    </div>
    <script>
        
        new Vue({
            el:"#root",
            data:{
                n:1
            },
            directives:{
                //函数何时被调用?
                //1.指令与元素成功绑定时(一打开页面)2.指令所在模板被重新解析时
                big(element,binding){
                    element.innerText=binding.value*10;
                },
                fbind:{
                    //方法何时被调用?
                    //指令与元素成功绑定时(一打开页面)
                    bind(element,binding){
                        console.log("bind"+this);	//注意,这里的this是window
                        element.value=binding.value;
                    },
                    //指令所在元素被插入页面时
                    inserted(element,binding){
                        element.focus()//元素获取焦点
                    },
                    //指令所在模板被重新解析时
                    update(element,binding){
                        element.value=binding.value;
                        element.focus()
                    }
                }
            }
        })
    </script>
</body>

在这里插入图片描述

一刷新页面或点击n+1按钮,自动把焦点放到输入框里

指令名由多个单词组成时用-隔开

<div v-big-number="n"></div>	<!--不要用驼峰式命名,就是不要命名为bigNumber,要用-隔开-->
<!--...-->
<script>
        
        new Vue({
            el:"#root",
            data:{
                n:1
            },
            directives:{
                //名字里有-用''包围
                'big-number'(element,binding){
                    element.innerText=binding.value*10;
                },
            }
        })
    </script>

自定义指令都是局部的,如果其他Vue对象是无法调用我的自定义指令的,当自定义指令变为全局的自定义指令时才能让多个Vue对象使用:

//设置全局的自定义指令方法1
        Vue.directive('big',function(element,binding){
                    element.innerText=binding.value*10;
        });

        //设置全局的自定义指令方法2
        Vue.directive('fbind',{
                    bind(element,binding){
                        element.value=binding.value;
                    },
                    inserted(element,binding){
                        element.focus()//元素获取焦点
                    },
                    update(element,binding){
                        element.value=binding.value;
                        element.focus()
                    }
                });

在这里插入图片描述

生命周期

在这里插入图片描述

<script>

        new Vue({
            el: "#root",
            data: {
                n: 1
            },
            beforeCreate() {
            },
            created() {
            },
            beforeMount() {
            },
            //Vue完成模板解析并把初始的真实DOM放入页面后(挂载完毕)调用mounted
            mounted() {
                //挂载
            },
            beforeUpdate() {
            },
            updated() {
            },
            beforeDestroy() {//这里可以做一些收尾工作
            },
            destroyed() {
            },
        })
    </script>

在这里插入图片描述

组件

非单文件组件

在这里插入图片描述

<body>
    <div id="root">
        <school></school>
        <student></student>
    </div>
    <script>
        //创建组件
        const mySchool = Vue.extend({
            template:`
            <div>
                <h2>学校名:{{schoolName}}</h2>
                <h2>地址:{{address}}</h2>    
            </div>
            `,
            data(){     //data一定要写成函数的形式
                return{
                    schoolName:'GGS',
                    address:'佛山'
                }
            }
        });
        const myStudent = Vue.extend({
            template:`
            <div>
                <h2>学生名:{{studentName}}</h2>
                <h2>年龄{{age}}</h2>    
            </div>
            `,
            data(){
                return{
                    studentName:'张三',
                    age:18
                }
            }
        });
        //全局注册的方式注册mySchool,这让即使在一个id为root2的容器里也能用这个组件
        Vue.component('student',mySchool);//第1个参数是名字,第2个参数是哪个组件
        new Vue({
            el: "#root",
            components:{
                //注册组件(局部注册),只能在id为root的容器里使用
                school:mySchool,//这一行直接写mySchool也可以,但是上面的标签也要改为mySchool
                //student:myStudent
            }
        })
    </script>
</body>

在这里插入图片描述

组件嵌套

在这里插入图片描述

<body>
    <div id="root">
    </div>
    <script>
        const student = Vue.extend({
            template:`
            <div>
                <h2>学生名:{{studentName}}</h2>
                <h2>年龄{{age}}</h2>    
            </div>
            `,
            data(){
                return{
                    studentName:'张三',
                    age:18
                }
            }
        });
        //创建组件
        const school = Vue.extend({
            template:`
            <div>
                <h2>学校名:{{schoolName}}</h2>
                <h2>地址:{{address}}</h2>
                <student></student>    
            </div>
            `,
            data(){
                return{
                    schoolName:'GGS',
                    address:'佛山'
                }
            },
            components:{
                student
            }
        });
        
        const app = Vue.extend({
            template:`<school></school>`,
            components:{
                school
            }
        })
        new Vue({
            el: "#root",
            template:`<app></app>`,
            components:{
               app
            }
        })
    </script>
</body>

在这里插入图片描述

VueComponent构造函数

在这里插入图片描述

Vue和VueComponent的关系

在这里插入图片描述

在这里插入图片描述

单文件组件

目录

在这里插入图片描述

School.vue

<template>
  <!-- 写html -->
  <!-- template里必须要有1个根结点 -->
  <div>
      <h3>{{name}}</h3>
  </div>
</template>

<script>//写js
export default {    //一般是这样写暴露出去
    name:'School',   //一般与文件名相同
    data(){
        return{
            name:'GGS'
        }
    }
}
</script>

<style>
/* 写css样式 */
</style>

App.vue

<template>
    <div>
        <School></School>
    </div>
</template>

<script>
import School from './School.vue'

export default {
    name:'App',
    components:{
        School
    }
}
</script>

<style>

</style>

main.js

import App from '../vue/App.vue'

new Vue({
    el:'#root',
    template:`<App></App>`,
    components:{
        App
    }
})

hello.html

<body>
    <div id="root">
    </div>
    <script src="./js/vue.js"></script>
    <script src="./js/main.js"></script>
</body>

脚手架

安装

首先安装node.js,我安装16.4版本后,安装vue脚手架出现问题安装失败,改为12.22版本就可以。 安装过程有个选项问是否安装python和C++工具,感觉打钩会比较好,因为之前16.4版安装脚手架时的报错就出现了python和C++的字眼,可能跟他们关。

安装node.js后切换国内镜像源加快下载速度

npm config set registry https://registry.npm.taobao.org

全局安装方式,安装脚手架

npm install -g @vue/cli

创建项目

vue create 项目名

然后会让你选择vue版本,选择自己对应的

运行项目

npm run serve

在这里插入图片描述

浏览器打开输入地址http://localhost:8080/

在这里插入图片描述

出现以上画面说明成功。

目录文件

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

脚手架相关

在这里插入图片描述

在这里插入图片描述

项目根目录下创建vue.config.js文件,可以做一些配置

module.exports = {
    // 选项...
    lintOnSave: false   //关闭语法检查
  }

ref属性

与html标签里的id属性差不多

在这里插入图片描述

School.vue

<template>
  <!-- 写html -->
  <!-- template里必须要有1个根结点 -->
  <div>
      <h3>{{name}}</h3>
  </div>
</template>

<script>//写js
export default {    //一般是这样写暴露出去
    name:'School',   //一般与文件名相同
    data(){
        return{
            name:'GGS'
        }
    }
}
</script>

<style>
/* 写css样式 */
</style>

App.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <School ref="school"></School>
    <span ref="title" v-text='msg'></span>
    <button @click="printDOM">点击打印DOM</button>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import School from './components/School.vue'

export default {
  name: 'App',
  components: {
    HelloWorld,
    School
  },
  data(){
    return{
      msg:'你好呀'
    }
  },
  methods: {
    printDOM(){
      console.log(this.$refs.title) //真实DOM
      console.log(this.$refs.school)  //School组件的实例对象
    }
  },
}
</script>

<style>
/*一些默认的样式*/
</style>

其他文件默认,运行后点击打印DOM按钮

在这里插入图片描述

在这里插入图片描述

props配置项

在这里插入图片描述

App.vue

<template>
  <div id="app">
    <!-- 这里写:num='18',这样传递的就是数字18,而不是字符串'18' -->
    <School ref="school" name='GGS' address='guangdong' ></School>
    <span ref="title" v-text='msg'></span>
    <button @click="printDOM">点击打印DOM</button>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import School from './components/School.vue'

export default {
  name: 'App',
  components: {
    HelloWorld,
    School
  },
  data(){
    return{
      msg:'你好呀'
    }
  },
  methods: {
    printDOM(){
      console.log(this.$refs.title) //真实DOM
      console.log(this.$refs.school)  //School组件的实例对象
    }
  },
}
</script>

School.vue

<template>
  <div>
      <h3>{{haha}}</h3>
      <h3>接收标签传来的属性</h3>
      <div>{{name}}</div>
      <div>{{address}}</div>
      <div>{{num}}</div>
  </div>
</template>

<script>//写js
export default {    //一般是这样写暴露出去
    name:'School',   //一般与文件名相同
    data(){
        return{
            haha:'哈哈'
        }
    },
    //项目运行时先接收props,再创建上方的data(){...}
    //简单接收标签里的属性
    //props:['name','address','num']

    //接收的同时对数据进行类型限制
    /* props:{
        name:String,
        address:String,
        num:Number
    } */

    //接收的同时对数据进行类型限制+默认值的指定+必要性的限制
    props:{
        name:{
            type:String,
            required:true   //name属性是必须要传过来的
        },
        address:{
            type:String
        },
        num:{
            type:Number,
            default:28		//没传过来就用默认值
        }
    }
}
</script>

<style>
/* 写css样式 */
</style>

mixin(翻译为混入)配置项

在这里插入图片描述

创建一个js文件,随意命名,里面可以存放一些可以多个组件通用的东西

//mixin.js
export const mixFunc = {
    methods: {
        showHello(){
            alert("你好呀~~~")
        }
    },
    data(){
        return {
            x:100
        }
    }
}

注意,这里的data有个x:100,如果引入mixin混入对象的组件里的data也有x(如x:200),那么以组件里的优先。(组件里的x不会变为100)

然后在需要用到这些通用东西的组件里进行引入(这种是局部引入):

School.vue

template>
  <div>
      <h3>{{haha}}</h3>
      <button @click="showHello">alertHello</button>
  </div>
</template>

<script>
import {mixFunc} from '../mixin'    //1.引入
export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈'
        }
    },
    mixins:[mixFunc]    //2.在mixins配置项里再写一次
}
</script>

<style>
</style>

全局引入:

在main.js里面导入mixin配置项:

import Vue from 'vue'
import App from './App.vue'
import {mixFunc} from './mixin' //1.导入

Vue.config.productionTip = false
Vue.mixin(mixFunc)  //2.全局配置
new Vue({
  render: h => h(App),
}).$mount('#app')

这样就不用在组件里面写mixin相关的配置了,全局引入导致项目里所有的VueComponent实例和Vue实例都拥有了mixin.js里的东西

插件

在这里插入图片描述

创建js文件,随意命名

export default {
    install(){
        console.log('plugin hello')
    }
}

main.js

import Vue from 'vue'
import App from './App.vue'
import plugins from './plugins'  //1.导入

Vue.config.productionTip = false
Vue.use(plugins)  //2.应用插件
new Vue({
  render: h => h(App),
}).$mount('#app')

scoped样式

在这里插入图片描述

每个组件里写的样式,最终都会汇总到一起的。这就有个问题,如果组件1写了个.test{}的样式,组件2也写了个.test{}的样式,这样名字重复了,就会导致最后导入到Vue的那个组件里的样式会覆盖其他重名的样式。

为了避免重名,可以在<style>标签内添加scoped,这样写的样式只给当前的文件用

注意,如果在App.vue里写样式,如.test{color:blue},那么导入到App.vue里的组件如果有用到 class=‘test’,那么就会应用App.vue的样式,所有字变为蓝色。为了避免错乱,在<style>标签内添加scoped,各管各的,互不干扰。

TodoList案例总结

在这里插入图片描述

浏览器存储

localStorage

关闭浏览器也不会清除,除非手动清除了浏览器的缓存之类的数据

localStorage.setItem(key,value);	//存储,value不论什么类型的值都会转为字符串存储
localStorage.getItem(key);		//获取
localStorage.removeItem(key);	//移除
localStorage.clear();		//清空

sessionStorage

关闭浏览器清除

sessionStorage.setItem(key,value);	//存储,value不论什么类型的值都会转为字符串存储
sessionStorage.getItem(key);		//获取
sessionStorage.removeItem(key);	//移除
sessionStorage.clear();		//清空

localStorage和sessionStorage统称webStorage

在这里插入图片描述

自定义事件

App.vue

<template>
  <div id="app">
    <!-- 1.给School组件绑定自定义事件showMsg 用v-on或@-->
    <!-- <School v-on:showMsg='getMsg'></School> -->

    <!-- 给School组件绑定自定义事件showMsg方式2 -->
    <School ref="school"></School>
  </div>
</template>

<script>
import School from './components/School.vue'

export default {
  name: 'App',
  components: {
    School
  },
  methods: {
    //2.创建方法接收数据
    getMsg(msg){
      console.log('App接收到:'+msg);
    }
  },
  mounted(){
    //绑定自定义事件方式2
    this.$refs.school.$on('showMsg',this.getMsg);
    //this.$refs.school.$once('showMsg',this.getMsg);   //只触发1次
  }
}
</script>

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <!-- 3.用按钮来演示 -->
      《<button @click="diyEvent">启动自定义事件</button>
  </div>
</template>

<script>
export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈',
            sayHello:'你好~'
        }
    },
    methods: {
        diyEvent(){
            //4.触发自定义事件并传递数据this.sayHello
            this.$emit('showMsg',this.sayHello);
        }
    },
}
</script>

解绑自定义事件

this.$off('showMsg')    //解绑1个自定义事件
//this.$off(['showMsg','abc'])    //解绑多个自定义事件
//this.$off()    //解绑所有自定义事件

在这里插入图片描述

全局总线

在这里插入图片描述

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
new Vue({
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus = this //1.安装全局事件总线
  }
}).$mount('#app')

App.vue

<template>
  <div id="app">
    <School></School>
  </div>
</template>

<script>
import School from './components/School.vue'

export default {
  name: 'App',
  components: {
    School
  },
  methods: {
    //2.创建方法接收数据
    getMsg(msg){
      console.log('App接收到:'+msg);
    }
  },
  mounted(){
    //3.给全局总线绑定事件
    this.$bus.$on('showMsg',this.getMsg);
  },
  beforeDestroy(){
    //5.这个组件销毁前把全局总线里自己定义的事件解绑
    //(组件都销毁了,那他绑定的事件自然也没用了,所以解绑)
    this.$bus.$off('showMsg');
  }
}
</script>

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <button @click="diyEvent">启动自定义事件</button>
  </div>
</template>

<script>
export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈',
            sayHello:'你好~'
        }
    },
    methods: {
        diyEvent(){
            //4.触发自定义事件并传递数据this.sayHello
            this.$bus.$emit('showMsg',this.sayHello);
        }
    },
    
}
</script>

消息订阅与发布

利用一个插件也能实现任意组件间通信

App.vue

<template>
  <div id="app">
    <School></School>
  </div>
</template>

<script>
import School from './components/School.vue'
import pubsub from 'pubsub-js'

export default {
  name: 'App',
  components: {
    School
  },
  methods: {
    //1.创建方法接收数据
    getMsg(msgName,data){
      console.log('App接收到:'+data);
    }
  },
  mounted(){
    //2.订阅消息
    this.pid = pubsub.subscribe('showMsg',this.getMsg);
  },
  beforeDestroy(){
      pubsub.unsubscribe(this.pid)
  }
}
</script>

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <button @click="diyEvent">启动自定义事件</button>
  </div>
</template>

<script>
import pubsub from 'pubsub-js'

export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈',
            sayHello:'你好~'
        }
    },
    methods: {
        diyEvent(){
            //3.发布消息
            pubsub.publish('showMsg',this.sayHello);
        }
    },
    
}
</script>

在这里插入图片描述

nextTick

在这里插入图片描述

动画效果

<template>
  <div id="app">
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!-- 显示到页面时<transition>标签会删除的,只保留里面的内容 -->
      <!-- vue动画效果利用<transition>标签 -->
    <transition>
      <h2 v-show="isShow">动画滑块</h2>
    </transition>
  </div>
</template>

<script>

export default {
  name: 'App',
  data(){
    return {
      isShow:true
    }
  }
  
}
</script>

<style>
  h2{background-color: rgb(19, 111, 185);}
  /*
  如果<transition name='abc'>标签里面有name属性,那么下面样式命名开头的v改为name的值
  v-enter-active这种是vue规定的命名
  */
  .v-enter-active{  
    animation: aaa 1s;
  }
  .v-leave-active{
    animation: aaa 1s reverse;
  }

  @keyframes aaa{
    from{
      transform: translateX(-100%);
    }
    to{
      transform: translateX(0px);
    }
  }
</style>

在这里插入图片描述

滑块可以向左移动隐藏和向右移动出现

过渡效果

<template>
  <div id="app">
    <button @click="isShow = !isShow">显示/隐藏</button>
     <!--如果transition表里里有多个子标签,把<transition>替换为<transition-group>-->
    <transition name="hello" appear>
      <h2 v-show="isShow">动画滑块</h2>
    </transition>
  </div>
</template>

<script>
export default {
  name: 'App',
  data(){
    return {
      isShow:true
    }
  }
}
</script>

<style>
  h2{background-color: rgb(19, 111, 185);}
  /* 进入的起点,离开的终点 */
  .hello-enter,.hello-leave-to{
    transform:translateX(-100%);
  }
  /* 进入的过程,离开的过程 */
  .hello-enter-active,.hello-leave-active{
    transition: 0.5s linear;
  }
  /* 进入的终点,离开的起点 */
  .hello-enter-to,hello-leave{
    transform: translateX(0);
  }
</style>

与动画效果一样,写法不同

第三方动画库

以Animate.css为例,具体参考官网:https://animate.style/

安装

npm install animate.css
<template>
  <div id="app">
    <button @click="isShow = !isShow">显示/隐藏</button>
    
    <transition name="animate__animated animate__bounce" appear
    enter-active-class="animate__backInDown" leave-active-class="animate__rubberBand">
      <h2 v-show="isShow">动画滑块</h2>
    </transition>
  </div>
</template>

<script>
import 'animate.css'  //1.引入

export default {
  name: 'App',
  data(){
    return {
      isShow:true
    }
  }
}
</script>

<style>
  h2{background-color: rgb(19, 111, 185);}
</style>

在这里插入图片描述

在这里插入图片描述

配置代理

解决跨域问题,也可以用nginx,这里用vue自带的

在这里插入图片描述

在这里插入图片描述

引入css资源的技巧

在这里插入图片描述

在public文件夹里创建css文件夹,再把css文件放进css文件夹,然后在index.html中引入,注意路径写法,这样就能生效了。

slot插槽

默认插槽

App.vue

<template>
  <div id="app">
    <School>abb</School>
  </div>
</template>

<script>
import School from './components/School.vue'

export default {
  name: 'App',
  components:{School}
}
</script>

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <!--如果调用School的人没有传东西就显示这句话-->
      <slot>slot默认值666</slot>
  </div>
</template>

<script>

export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈'
        }
    },
}
</script>

在这里插入图片描述

如果<School>abb</School>里没有内容,即<School></School>,就会把<slot>slot默认值666</slot>的内容放到

<School></School>里,即<School>slot默认值666</School>

插槽命名

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <slot name="sl1">slot默认值,如果调用School的人没有传东西就显示这句话1</slot>
      <slot name="sl2">slot默认值,如果调用School的人没有传东西就显示这句话2</slot>
      <slot name="sl3">slot默认值,如果调用School的人没有传东西就显示这句话3</slot>
  </div>
</template>

<script>

export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈'
        }
    },
}
</script>

App.vue

<template>
  <div id="app">
    <School>
      <h3 slot="sl1">插槽1</h3>
      <h3 slot="sl2">插槽2</h3>
      <!-- 插槽另一种用法,配合<template></template> -->
      <template v-slot:sl3>
        <h3>插槽3</h3>
      </template>
    </School>
  </div>
</template>

<script>
import School from './components/School.vue'

export default {
  name: 'App',
  components:{School}
}
</script>

在这里插入图片描述

作用域插槽

School.vue

<template>
  <div>
      <h3>School,{{haha}}</h3>
      <slot :childData='games'>slot默认值,如果调用School的人没有传东西就显示这句话1</slot>
  </div>
</template>

<script>

export default {   
    name:'School',   
    data(){
        return{
            haha:'哈哈',
            games:['cs','cf']
        }
    },
}
</script>

App.vue

<template>
  <div id="app">
    <School>
      <template scope="childData">
        {{childData}}
        <ul>
          <li v-for="(g,index) in childData.childData" :key='index'>{{g}}</li>
        </ul>
      </template>
    </School>
  </div>
</template>

<script>
import School from './components/School.vue'

export default {
  name: 'App',
  components:{School},
}
</script>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Vuex

在js文件中,import语句无论写在第几行,vue都会自动把所有import语句汇总到最上方。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

路由

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

简单实例

目录

在这里插入图片描述

main.js

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import router from './router/index'

Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
  render: h => h(App),
  router:router
}).$mount('#app')

src/router/index.js

//用于创建整个项目的路由器
import VueRouter from "vue-router";
import School from '../components/School.vue'
import Student from '../components/Student.vue'

//创建1个路由
export default new VueRouter({
    //配置路由
    routes:[
        {
            path:'/school', //请求路径
            component:School
        },
        {
            path:'/student',
            component:Student
        }
    ]
})

index.html 引入bootstrap样式

<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">

School.vue

<template>
    <div>
      <h3>我是School</h3>
  </div>
</template>

<script>
export default {   
    name:'School',   
}
</script>

Student.vue

<template>
  <div>
      <h3>我是Student</h3>
  </div>
</template>

<script>
export default {
    name:'Student'
}
</script>

App.vue

<template>
  <div class="container">
    <h1>我的第一个 Bootstrap 页面</h1>
    <div class="row">
      <div class="col-lg-4">
          <ul class="list-group"> 
            <!-- router-link在页面中会自动变为a标签,to与a标签的href属性类似 
              active-class=" active"  告诉路由当被点击时应用active 的class样式
            -->
            <router-link class="list-group-item" active-class=" active" to="/school">School</router-link>
            <router-link class="list-group-item" active-class=" active" to="/student">Student</router-link>
        </ul>
      </div>
      <div class="col-lg-8">
        <!-- 指定组件的显示位置 -->
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

效果

在这里插入图片描述

在这里插入图片描述

多级路由

在这里插入图片描述

路由query传参

就类似浏览器里路径传参数 http://localhost:8080/student?id=123&name=tom

在这里插入图片描述

接收参数可以:<h3>{{$route.query.id}}</h3>

路由命名

在这里插入图片描述

在这里插入图片描述

路由params传参数

就类似浏览器里路径传参数 http://localhost:8080/student/123/name 123就是我的参数

在这里插入图片描述

在这里插入图片描述

实例:

src/router/index.js

//用于创建整个项目的路由器
import VueRouter from "vue-router";
import School from '../pages/School.vue'
import Student from '../pages/Student.vue'

//创建1个路由
export default new VueRouter({
    //配置路由
    routes:[
        {
            name:'schoolName',
            path:'/school/:id', //params传参数 :占位符声明
            component:School
        },
        {
            path:'/student',
            component:Student
        }
    ]
})

App.vue

<template>
  <div class="container">
    <h1>我的第一个 Bootstrap 页面</h1>
    <div class="row">
      <div class="col-lg-4">
          <ul class="list-group"> 
            <!-- params传参数方式1 -->
            <!-- <router-link class="list-group-item" active-class=" active" :to="`/school/${123}`">School</router-link> -->
            
            <!-- params传参数方式2 -->
            <router-link class="list-group-item" active-class=" active" :to="{
              name:'schoolName',
              params:{
                id:123
              }
            }">School</router-link>
            <router-link class="list-group-item" active-class=" active" to="/student">Student</router-link>
        </ul>
      </div>
      <div class="col-lg-8">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

School.vue

<template>
    <div>
      <h3>我是School</h3>
      <h3>{{$route.params.id}}</h3>
  </div>
</template>

<script>
export default {   
    name:'School',   
}
</script>

在这里插入图片描述

路由的props配置

在这里插入图片描述

路由组件接收参数:

<script>
export default {   
    name:'School',
    props:['id']   //接收参数
}
</script>

router-link的replace属性

在这里插入图片描述

编程式路由导航

在这里插入图片描述

缓存路由组件

在这里插入图片描述

include里写的是组件名

<script>
export default {
	name:'News',	//组件名
....
}
</script>

如果不写include则<router-view>里的所有组件页面都会被缓存。

如果有多个组件需要被缓存,要把include写为数组形式:

<keep-alive :include="['News','School']">
    <router-view></router-view>
</keep-alive>

使用场景:

有2个导航项,对应有2个页面。页面1里有输入框,用户输入了一些内容,然后点击导航项2去到页面2,再点击导航项1回到页面1,输入框里的内容没有被清空,依然存在。

属于路由组件的生命周期

在这里插入图片描述

<script>
export default {
....
	activated(){	//激活时调用
	...
	},
	deactivated(){	//失活时调用
	...
	}
}
</script>

如有2个组件页面,从组件1切换到组件2,组件1此时就失活了,从组件2再切换到组件1,组件1此时就激活了。

路由守卫

全局路由守卫

在这里插入图片描述

meta:开发者可以在meta里放一些自定义的数据

src/router/index.js

//创建1个路由器
export default new VueRouter({
    //配置路由
    routes:[
        {
            name:'schoolName',
            path:'/school/:id',
            component:School,
            meta:{title:'你好'}
        },
        ]
 })

独享路由守卫

在这里插入图片描述

//创建1个路由器
export default new VueRouter({
    //配置路由
    routes:[
        {
            name:'schoolName',
            path:'/school/:id',
            component:School,
            meta:{title:'你好'},
            beforeEnter: (to, from, next) => {
                // ...
            }
        },
        ]
 })

守卫配置在1个路由内,就只给这一个路由使用,其他不管。

组件内守卫

to,from,next的意思与上面的一样

在这里插入图片描述

写在组件里面:

<script>
export default {
    name:'Student',
    beforeRouteEnter (to, from, next) {
      // ...
    },
    beforeRouteLeave (to, from, next) {
      // ...
    }
}
</script>

路由器的两种工作模式:hash和history

在这里插入图片描述

src/router/index.js

export default new VueRouter({
    mode:'history'	//工作模式,默认是hash
    //配置路由
    routes:[
    ......
    ]
})

hash模式路径里会有#,history没有

项目打包

在这里插入图片描述

把public和src文件夹里的文件打包变为js、css、html文件

npm run build

生成的dist文件夹就是打包好的项目了

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 08:56:16  更:2021-08-28 08:57:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:13:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码