
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>01-初识vue.html</title> <!-- 0、导入vue.js --> <script src="../js/vue.js"></script> </head> <body> <!-- 1、定义一个容器 --> <div id="app"> <h3> 第一个vue程序,并使用插值表达式取得值为:{{name}} </h3> </div> </body> <script> // 去除浏览器控制台中的错误信息 Vue.config.productionTip = false; // 2、初始化Vue容器 new Vue({ el: "#app", data: { name: "紫邪情", age: "18" } }) </script> </html>启动效果如下:
初识Vue小结
<!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"> <title>02-vue之v-bind</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 常规写法:v-bind绑定的是属性 --> <a v-bind:href="url"></a> <!-- 多层嵌套取值:插值表达式 取的东西就是下面Vue实例new Vue({}) data中的东西,可以理解为在找寻集合中的元素 --> <h3>{{person.name}}</h3> <!-- 简写 --> <h3 :mySex="person.sex">{{person.name}}</h3> </div> </body> <script> Vue.config.productionTip = false; new Vue({ el: "#app", // el指定的是为哪一个容器服务 值就是一个css中的选择器 data: { // data存储的就是数据,这些数据是供el指定的容器去用的 url: "https://www.cnblogs.com/xiegongzi/", person: { name: "紫邪情", sex: "女" } } }) </script> </html>启动效果
<!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"> <title>03-v-model</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 单向绑定:绑的是属性 --> 单向绑定:<input type="text" :value="name"> <br/> <!-- 双向绑定:绑的是值 --> 双向绑定:<input type="text" :myName="name" v-model:value="username"> <br/> <!-- 双向绑定的简写 因为:model绑的就是值,因此:value可以省掉 --> 双向绑定:<input type="text" :myName="name" v-model="username"> </div> </body> <script> Vue.config.productionTip = false; new Vue({ el: "#app", data: { name: "紫邪情", username: "邪公子" } }) </script> </html>效果如下:
测试单向绑定

测试双向绑定

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>04-vue的el和data的两种写法</title> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"></div> <script> // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 // el:'#app', // el 常规写法 // data:{}, // data 常规写法 ———— 这种也叫对象式写法 // data 函数式写法,这种写法后续经常见 data () { // 这里使用data:function(){}也可以,但是:绝对不能写成data:()=>{} // 因为这种写法变质了,成为Window对象了,这样后续用this指向时,这个this所指代的就不Vue实例了 return { } } }); // el 另外的写法 vm.this.$mount('#app') // 此种写法需要记住,后续组件化开发还会见到 </script> </body> </html>小结:el和data的两种写法
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>理解MVVM</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>姓名:{{name}}</h2> <br> <h2>性别:{{sex}}</h2> <hr> <h2>智商:{{1+1}}</h2> </div> <script> // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ name: "紫邪情", sex: "女" }, }); console.log( vm ); </script> </body></html> 


查看代码中的MVVM
小结:MVVM模型
观察效果发现

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>05-了解object.defineProperty()</title> <script src="../js/vue.js"></script> </head> <body> <script> Vue.config.productionTip=false; let sex = '女' let person = { name: '紫邪情' } // 参数说明:person 为要修改的对象 sex为具体修改的对象中的哪个属性 {} 对修改属性的配置 Object.defineProperty( person , 'sex' , { // 以下就是{}中的相关配置 // value: '男', // enumerable: true, // 这个sex是否可以被遍历 // writable: true, // 这个sex是否可以被修改 // configurable: true, // 这个sex是否可以被删除 // 当有人获取sex这个属性时会触发这个get()方法 get(){ console.log('有人读取sex属性了'); return sex; }, // 当有人修改sex属性的值时会触发这个set方法 set(value){ console.log('有人修改了sex的值'); return sex = value; } }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>06-简单理解数据代理</title> </head> <body> <script> let obj1 = {x:100}; let obj2 = {y:200}; // 数据代理: 通过一个对象代理 对 另一个对象中属性的操作( 读 / 写 ) Object.defineProperty(obj2 , 'x' , { get(){ console.log("有人获取了x的值"); return obj1.x; }, set(value){ console.log("有人修改了x的值"); obj1.x = value; } }) </script> </body> </html>原理图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>07-事件绑定及其修饰符</title> <script src="../js/vue.js"></script> </head> <!-- 常用的事件修饰 prevent 表示:阻止默认事件的触发 stop 表示:阻止事件冒泡 once 表示:只执行一次事件 --> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <!-- vue中事件绑定的简单写法 --> <button v-on:click="showInfo()">点我显示提示信息</button> <br/> <!-- vue中事件绑定的简写 还可以传递参数 --> <button @click="showInfo2($event, 66)">点我获取带参的事件信息</button> </div> <script> Vue.config.productionTip=false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{}, methods: { showInfo(){ alert("这是vue中的事件绑定"); }, showInfo2(event , number){ console.log(event + "=====>" + number); } } }); </script> </body> </html> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>10-计算属性conputed</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> 姓名: <input type="text" v-model="name"> <br/> 性别: <input type="text" v-model="sex"> <hr> 信息: <span>{{info}}</span> </div> <script> Vue.config.productionTip=false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ name:'紫邪情', sex:'女' }, // 所谓的计算属性:就是通过已有属性( 一般为data中的 )计算得来 computed: { info:{ get(){ console.log('开始调用get()'); return this.name + '-' + this.sex }, set(value){ console.log('开始调用set()' + value); } } } }); </script> </body> </html>
计算属性小结
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>11 - 使用计算属性做一个Demo</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>你是:{{result}}</h2> <button @click="changeResult">切换名字</button> </div> <script> // 去除浏览器控制台中的错误信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ name: true }, computed:{ result(){ return this.name?'紫邪情':'紫女' } }, methods: { changeResult(){ return this.name = !this.name } }, }); </script> </body> </html>

但是:上面的代码其实是可以做简化的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>12 - 使用计算属性做一个Demo 简化</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>你是:{{result}}</h2> <!-- @xxx = 'yyyy' 如果只是做一件简单的事情,那么就可以使用下面的方式 因为:v-on是可以支持js表达式的( 注意:不是js代码啊 ) 但是:如果这个v-on需要做多件事,那么最好就别这么玩 如:切换了名字,还要弄一个弹窗( 切换成功 )这种就别玩 --> <button @click="name = !name">切换名字</button> </div> <script> // 去除浏览器控制台中的错误信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ name: true }, computed:{ result(){ return this.name?'紫邪情':'紫女' } }, // methods: { // changeResult(){ // return this.name = !this.name // } // }, }); </script> </body> </html> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>13 - 监视属性 watch</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>你是:{{result}}</h2> <button @click= "name = !name">切换名字</button> </div> <script> // 去除浏览器控制台中的错误信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ name: true }, computed: { result() { return this.name?'紫邪情':'紫女' } }, // 监视属性 watch 监视的是属性,也就是data中和computed中的都可以监视 // 现在这种我是用的简写形式 ———— 前提是:只需要使用handler()中的东西时,handler后续会用完整形式 watch: { name( newValue, oldVaule ){ // 表示的是:监视哪个属性 console.log('属性发生变化了' , newValue , oldVaule); } }, }); // 当然:监视属性还有一种写法,就是利用Vue的内置函数 /* vm.$watch( 'name', { // 这里的name就是指监听哪个属性 而且必须是' '引起来的 handler( newValue, oldVaule ){ console.log('属性发生变化了' , newValue , oldVaule); } }) */ </script> </body> </html> 
监视属性 watch小结
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>14 - 深度监视</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>你是:{{result}}</h2> <!-- 现在这个name就是person里面的了,这就是需要监视多层属性变化 --> <button @click= "person.name = !person.name">切换名字</button> </div> <script> // 去除浏览器控制台中的错误信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ person:{ name: true } }, computed: { result(){ return this.person.name?'紫邪情':'紫女' } }, // 下面这种事监视属性的完整写法 watch: { person:{ // 监视多层结构中所有属性的变化 deep: true, // 深度监视 就做了这一步操作而已 /* Vue中watch默认是不可以监视属性更里层的, 如:上面person只可以监视person本身这个属性,理解的话, 可以采用对象空间值来比对,假如:person空间地址是是01x23, 那么Vue只会监视这个空间变量有没有发生改变,而内层就不可以监视, 因为:内层中的属性改变了,但是person这个对象本身并没有改变 */ handler(){ console.log('属性改变了'); } } } }); </script> </body> </html>
深度监视小结
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>15 - computed和watch的坑</title> <script src="../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> 姓: <input type="text" v-model="firstname"> <br/> 名: <input type="text" v-model="lastname"> <hr/> 信息: {{fullname}} </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ firstname: '紫', lastname: '邪情', fullname: '紫邪情' }, watch: { firstname(val){ this.fullname = val + this.lastname; }, lastname(val){ this.fullname = this.firstname + val; } } }); </script> </body> </html>

用computed实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>02 - computed实现</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> 姓: <input type="text" v-model = "firstname"> <br/> 名: <input type="text" v-model = "lastname"> <hr/> 信息: {{fullname}} </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ //指定控制的区域 el:'#app', data:{ firstname: '紫', lastname: '邪情' }, computed: { fullname(){ return this.firstname + this.lastname; } } }); </script> </body> </html>最后运行的效果都是一样的,而官网中对这二者有着这样的实例演示
但是:虽然看起来没区别,可是computed和watch还是有区别的,假如:现在我需要让姓改了之后,隔1s之后再显示到信息那里。那么:computed无法做到,但是watch就可以
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>03 - 用watch实现异步操作</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> 姓: <input type="text" v-model = "firstname"> <br/> 名: <input type="text" v-model = "lastname"> <hr/> 信息: {{fullname}} </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ firstname: '紫', lastname: '邪情', fullname: '紫邪情' }, watch: { firstname(val){ // 一定需要注意:这里必须使用兰姆达表达式() =>{} /* 前面说过,Vue所管理的函数,切记别用兰姆达表达式,智能用函数式 这是为了能够通过this拿到vm实例的东西而已 但是注意:这里这个setTimeout()定时函数是Vue所管理的吗? 不是,而后面需要的val是哪里的?是Vue实例中的,修改的值 是在Vue实例身上 所以:想要拿到Vue身上的val怎么弄?页面的展示都是js引擎帮忙去进行操作 / 找寻的 因此:利用js引擎做文章,让它找的时候自动去层级查找,它执行到里面的this.fullname = val + this.lastname时 会去找this是谁,()=>{}这里是用的兰姆达表达式,这就会指向Window对象,而Window上没有fullname,所以就会 往外找,找到firstname(val)这是函数式,指向的就是Vue实例,也就找到了fullname、val..... */ setTimeout( () => { this.fullname = val + this.lastname; }, 1000); }, lastname(val){ this.fullname = this.firstname + val; } } }); </script> </body> </html> 

computed和watch的区别
假如有如下的一个页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>01 - class样式绑定</title> <script src="../../js/vue.js"></script> <style> body { background-image: url(img/bg3.jpg); text-align: center; background-size: 100% 100%; height: 100%; overflow: hidden; background-repeat: no-repeat; background-position: center; background-attachment: fixed; } .top { background: #ffffff2e; width: 100%; position: absolute; bottom: 0; line-height: 60px; left: 0px; right: 0px; color: #fff; text-align: center; font-size: 16px; font-weight: 600; } .basicLogin { position: absolute; top: 16%; left: 28.5%; width: 40%; padding: 70px 2%; text-align: center; } .title { font-weight: 600; font-size: 22px; color: #0000FF; margin-bottom: 40px; } .line { border-bottom: 1px solid #ffff; margin: 22px 1%; width: 96%; } .line input { border: none; padding: 0px 1%; margin: 1%; background: #ffffff14; width: 84%; font-size: 16px; line-height: 30px; outline: none; } .line .smallImg { width: 26px; float: left; vertical-align: middle; margin-top: 1px; } .logBut { background: #7bb5ee; padding: 10px 80px; border: none; color: #fff; margin-top: 40px; font-size: 16px; cursor:pointer; } </style> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <div >©紫邪情 · 用Java改变未来</div> <div > <div >©紫邪情 · 登录</div> <div > <img src="img/icon-4.png" /> <input placeholder="请输入账号" type="text" /> </div> <div > <img src="img/icon-5.png" /> <input placeholder="请输入密码" type="password" /> </div> <button type="button" >登 录</button> </div> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{}, }); </script> </body> </html>效果图如下
现在需求1、中间的登录页样式,不要这种,想要换一种:假如是如下这种
.login1 { background: #ffffffd6; border-radius: 2px; }

.login2 { background: rgba(0,0,0,.8); box-sizing : border-box; box-shadow: 0 15px 25px rgba(0,0,0,.5); border-radius: 10px; }

因此:此时这个class的名字不确定到底是哪一个,需要动态去绑定,所以通过Vue来动态绑定一下( 即:把class类名交给Vue托管 )
class类名不确定,交由Vue托管很简单,而且知识点前面已经学过了,就是v-bind
<body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <div >©紫邪情 · 用Java改变未来</div> <div :class = "unknown" @click = "changeLogin"> <div >©紫邪情 · 登录</div> <div > <img src="img/icon-4.png" /> <input placeholder="请输入账号" type="text" /> </div> <div > <img src="img/icon-5.png" /> <input placeholder="请输入密码" type="password" /> </div> <button type="button" >登 录</button> </div> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ unknown: 'login1' }, methods: { changeLogin(){ if( this.unknown === 'login1'){ this.unknown = 'login2' }else{ this.unknown = 'login1' } } } }); </script> </body>

需求2、现在class类名的个数、名字都不确定

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>2 - 数组写法</title> <script src="../../../js/vue.js"></script> <style> body { background-image: url(../img/bg3.jpg); text-align: center; background-size: 100% 100%; height: 100%; overflow: hidden; background-repeat: no-repeat; background-position: center; background-attachment: fixed; } .top { background: #ffffff2e; width: 100%; position: absolute; bottom: 0; line-height: 60px; left: 0px; right: 0px; color: #fff; text-align: center; font-size: 16px; font-weight: 600; } .basicLogin { position: absolute; top: 16%; left: 28.5%; width: 40%; padding: 70px 2%; text-align: center; } .login1 { background: #ffffffd6; border-radius: 2px; } .login2 { background: rgba(0,0,0,.8); box-sizing : border-box; box-shadow: 0 15px 25px rgba(0,0,0,.5); border-radius: 10px; } .title { font-weight: 600; font-size: 22px; color: #0000FF; margin-bottom: 40px; } .line { border-bottom: 1px solid #ffff; margin: 22px 1%; width: 96%; } .line input { border: none; padding: 0px 1%; margin: 1%; background: #ffffff14; width: 84%; font-size: 16px; line-height: 30px; outline: none; } .line .smallImg { width: 26px; float: left; vertical-align: middle; margin-top: 1px; } .logBut { background: #7bb5ee; padding: 10px 80px; border: none; color: #fff; margin-top: 40px; font-size: 16px; cursor:pointer; } </style> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <div >©紫邪情 · 用Java改变未来</div> <div :class = "unknown" @click = "changeLogin"> <div >©紫邪情 · 登录</div> <div > <img src="../img/icon-4.png" /> <input placeholder="请输入账号" type="text" /> </div> <div > <img src="../img/icon-5.png" /> <input placeholder="请输入密码" type="password" /> </div> <button type="button" >登 录</button> </div> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ unknown: [ 'login1' , 'login2' ] }, methods: { changeLogin(){ const arr = [ 'login1' , 'login2' ]; this.unknown = arr[ Math.floor( Math.random() * 2 ) ] } } }); </script> </body> </html>
需求3、要绑定的class名字确定,但是:个数不确定,也需要动态绑定

class样式绑定小结


class和style样式绑定小结
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - v-if</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <!-- v-if和java中的if一样,只要结果为true就执行,为false就不执行 所以:这里面不用true,用 1 === 1 也行, 当然:使用v-bind绑定,写到data中,只要最后结果为boolean值即可 相应地:有了v-if,那当然也有v-else-if、v-else( 不过这个有点特殊 这是什么条件都不满足的时候,最终执行的[ 类似于java的try....catch....finally 中的finally ] --> <div v-if = "true"> <img :src="result" alt="不见了影响你开法拉利不?" :> </div> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ result: 'img/19.jpg', obj: { width: '500px', hight: '500px' } }, }); </script> </body> </html>






v-if会了,v-show就会了,用法和单纯的v-if一模一样
不过它和v-if的原理不一样

v-if和v-show小结

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - 认识v-for</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <!-- 1、遍历数组 --> <h2>人员信息</h2> <!-- 简写形式 --> <ul> <li v-for = "p in persons" :key="p.id"> {{p.name}} ----- {{p.age}} </li> <!-- v-for就和js中的for in差不多 :key="p.id" 此处:是给每一个li节点一个唯一的id( 和身份证号一样 就相当于是<li id = ‘xxx’> ),此时不写没事,但是最好都带上,后续有用 p 代表的就是:从persons中遍历出来的每一条数据 --> </ul> <!-- 完整写法 --> <ul> <li v-for = "(val,index) in persons" :key="val.id"> {{val.name}} ----- {{val.age}} ------ {{index}} </li> </ul> <!-- 2、遍历对象 --> <h2>神奇之地</h2> <ul> <li v-for = "(val,index) in like" :key="index"> {{val}} ------ {{index}} </li> </ul> <!-- 其实另外还有:v-for还可以遍历字符串、某个数字( 循环这个数字这么多次 ),但是这两种基本上都不用,所以不说明了 --> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ persons: [ // 数组中又放得有对象 {'id':'10001','name':'紫邪情','age':'18'}, {'id':'10002','name':'紫女','age':'18'}, {'id':'10003','name':'邪公子','age':'19'} ], like: { name: '香牌坊', ko:'范冰冰' } }, }); </script> </body> </html> 
v-for小结

实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>2 - key值的坑</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>人员信息</h2> <ul> <!-- 这里使用index作为key值 --> <li v-for = " (p , index) in persons" :key="index"> {{p.name}} ----- {{p.age}} <input type="text"> </li> </ul> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ persons:[ {'id':'001' , 'name':'张三','age':'18'}, {'id':'002' , 'name':'李四','age':'19'}, {'id':'003' , 'name':'王五','age':'20'} ] }, }); </script> </body> </html>效果如下
现在有这么一个需求:想要在“张三”的前面添加一条“老刘”数据( 这里使用页面button添加,不是直接在data中添加)
效果如下



为什么会发生上面的问题,来看看原理图,了解用index做key值的坑
了解了上面的index作为key值,那么用数据id作为key值也懂了
其中:图中的对比算法就是所谓的“diff算法”
而不写key的话,Vue做了一件默认的操作,就是把遍历的index作为了key值,也就是和前面使用index作为key值是一样的效果了
把以上的内容,换成文字小结一波
Vue中的key有什么作用( 原理是什么? )【 不止Vue啊,React中的key也是同样的原理,前面说过React核心就是虚拟DOM 】
1、虚拟DOM中key的作用
2、对比算法的规则
3、用index作为key值可能会引发的问题
(1)、若对数据进行:逆序添加、逆序删除.....等破坏数据顺序的操作

所谓的逆序操作就是数据添加在前面( 如:例子中是添加在“张三”前面的,但是:在最后添加( 即:在例子中“王五”后面添加数据,这种在最后面添加,则:在新虚拟DOM中生成真实DOM时,顺序是对的,不会出现上述问题的 )

(2)、若结构中还包含输入类的DOM( 如:例子中的input )
4、开发中如何选择key?
1、使用watch实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>3 - 列表过滤( 查询功能 )</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <H2>人员信息列表</H2> 搜索:<input type="text" placeholder="请输入搜索词" v-model="keyWord"> <ul> <li v-for = " p in filterPersons" :key="p.id"> {{p.name}} -------- {{p.age}} </li> </ul> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ // 1、搜集搜索框中的内容 搜索框内容变,这里的内容也要变,所以:双向绑定v-model keyWord: '', // 2、准备初始数据 persons: [ {'id':'10001','name':'紫邪情','age':'18'}, {'id':'10002','name':'紫邪晴','age':'19'}, {'id':'10003','name':'邪公子','age':'20'}, {'id':'10004','name':'公孙策','age':'21'}, {'id':'10005','name':'孙悟空','age':'22'} ], // 4、需要准备另一个容器来装过滤之后的数据 filterPersons: [] }, // 3、使用watch来实现搜索效果 /* 需要做两件事 (1)、拿到data的keyWord中的内容 (2)、使用keyWod中的内容 去 persons中进行过滤筛选,从而把结果渲染到页面 */ watch: { keyWord: { // 这个的作用:页面初始化时就执行一次handler() immediate: true, handler(newVal){ // 1)、过滤数据 把结果放到filterPersons中去 this.filterPersons = this.persons.filter( (p)=>{ // 没在数组中indexOf()返回的就是-1 return p.name.indexOf(newVal) !== -1 }) } } } }); </script> </body> </html>效果如下

2、使用computed实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>3 - 列表过滤( 查询功能 )</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <H2>人员信息列表</H2> 搜索:<input type="text" placeholder="请输入搜索词" v-model="keyWord"> <ul> <li v-for = " p in filterPersons" :key="p.id"> {{p.name}} -------- {{p.age}} </li> </ul> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ // 1、搜集搜索框中的内容 搜索框内容变,这里的内容也要变,所以:双向绑定v-model keyWord: '', // 2、准备初始数据 persons: [ {'id':'10001','name':'紫邪情','age':'18'}, {'id':'10002','name':'紫邪晴','age':'19'}, {'id':'10003','name':'邪公子','age':'20'}, {'id':'10004','name':'公孙策','age':'21'}, {'id':'10005','name':'孙悟空','age':'22'} ], }, // 3、使用computed来实现搜索效果 /* 需要做两件事 (1)、拿到data的keyWord中的内容 (2)、使用keyWod中的内容 去 persons中进行过滤筛选,从而把结果渲染到页面 */ computed: { filterPersons() { return this.persons.filter( (p)=>{ return p.name.indexOf( this.keyWord ) !== -1 }) } } }); </script> </body> </html>效果如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>4 - 列表排序</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>人员信息</h2> 搜索: <input type="text" v-model = "keyWoed" placeholder="请输入关键字"> <button @click = "sortType = 1">升序</button> <button @click = "sortType = 2">降序</button> <button @click = "sortType = 0">原顺序</button> <ul> <li v-for = " p in filterPersons" :key="p.id"> {{p.name}} ----- {{p.age}} </li> </ul> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ keyWoed: '', sortType: 0, persons: [ {'id':'10001','name':'紫邪情','age':'18'}, {'id':'10002','name':'紫邪晴','age':'14'}, {'id':'10003','name':'邪公子','age':'121'}, {'id':'10004','name':'公孙策','age':'21'}, {'id':'10005','name':'孙悟空','age':'42'} ] }, computed: { filterPersons(){ /* 排序:就是将列表过滤之后的数据 根据特定字段排序之后,再渲染到页面中即可 因此:return this.persons.filter这里不能直接用return,不然就直接把过滤的数据渲染到页面了 所以:再对这一步做一下排序操作 */ // 先用个数组装起来 const arr = this.persons.filter( (p)=>{ return p.name.indexOf( this.keyWoed ) !== -1; }) // 然后对数组进行排序操作,但是得先知道用户是点击的哪个按钮( sortType ) if (this.sortType) { arr.sort( (previous,last)=>{ return this.sortType == 1 ? previous.age - last.age : last.age - previous.age; }) } return arr; } } }); </script> </body> </html>效果如下




先来看看Vue检测属性失效的问题,从而引申处Vue监视数据的原理
先来玩正常版
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - 监视数据失效实例</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>Vue监视数据失效问题</h2> <ul> <li v-for = "p in persons" :key="p.id"> {{p.name}} ---- {{p.age}} </li> </ul> <button @click = "update">修改数据</button> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ persons: [ {'id':'10001','name':'紫邪情','age':'18'} ] }, methods: { update(){ this.persons[0].name = '紫女'; } } }); </script> </body> </html> 

现在变一下,整出bug




玩这个就需要又回到前面玩过的“数据代理”了
前面就说过,这个数据代理,只是简单了解而已,上面的流程其实不算对,因为少了一个步骤,整个流程应该是:自己写的data ————> 对data进行加工 —————> 把data中的数据给_data ————> 再把_data的内容给页面需要的data中( 即:这一步相当于执行了 vm._data = data , 这个data就是页面上的data嘛,所以就成功地让页面中的数据跟着自己的修改而改变了,但是底层不是用 vm._data = data,方法名不一样,而且还要更复杂一点
来回顾一下例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>3 - 回顾数据代理</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2> 姓名: {{person.name}} </h2> <br/> <h2> 性别: {{person.sex}} </h2> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ person: { name: '紫邪情', sex: '女' } }, }); </script> </body> </html>
根据上面的原理,简单模拟一个vue的数据监视
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>4 - 模拟Vue数据监视</title> </head> <body> <script> // 准备一个对象 let data = { name: '紫邪情', sex: '女' } // vue做了精妙之一就是:设计了一个构造方法Observer(传对象名),这个东西刚刚在_data中见过它,打开就是用Observer打开的 function Observer(obj) { // 拿到data中的所有key值( 即:上面的name、sex ),放到一个数组里面去 const keys = Object.keys( obj ); // 遍历这些key值,得到每一个key keys.forEach( (key) => { // 使用defineProperty()做数据代理 这里的this就是指:传的对象 Object.defineProperty( this, key , { get(){ return obj[key]; }, set(val){ console.log( "值被修改了,要开始解析数据、生成虚拟DOM、进行对比算法、响应数据了"); obj[key] = val; } }) }); } // 调用设计的构造方法,从而开始做 data 转 _data const objs = new Observer(data); let vm = {}; vm._data = data = objs console.log( objs ); </script> </body> </html>

实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>5 - 了解Vue.set( target, key, val )</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2> 姓名: {{person.name}} </h2> <br/> <h2> 性别: {{person.sex}} </h2> <br/> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ person:{ name: '紫邪情', sex: '女' } }, }); </script> </body> </html>效果如下
现在有个需求:需要添加一个属性 age: 18,不可以直接添加在data中,这样就没意义了

当然:还有一种方式也可以实现
上面这是正常情况,我说了target这个参数有坑,官网有介绍
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>6 - target参数的坑</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2> 姓名: {{name}}</h2> <br/> <h2> 性别: {{sex}}</h2> <br/> <h2 v-if = "age"> 年龄: {{age}}</h2> <button @click = "addAge">添加年龄属性</button> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ // 把这里的属性换一下位置,不用person{}对象包起来,直接放到data中 name: '紫邪情', sex: '女' }, methods: { addAge(){ this.$set( this.data, 'age', 18); } } }); </script> </body> </html>
写个正常例子,去控制台看数组的结构
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - 正常实例 - 控制台查看结构</title> <script src="../../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>爱好</h2> <ul> <li v-for = "(h , index) in hobby" :key="index"> <h2> {{h}} </h2> </li> </ul> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ hobby: [ '吃', '喝', '嫖', '赌', '要不得'] }, }); </script> </body> </html>
那么我们在控制台把数据改了呢?会不会响应到页面上?
上面这个问题就和前面一开始的问题一样了:监视数据失效的问题
这二者都是使用的"索引"来找的数组的具体某个值,而这:恰恰就是一个坑,想一下在Vue中我们操作数组是怎么做的?是通过数组调了对应的API,如:arr.push()、arr.shift()........,那Vue怎么知道我调的是哪个API( 换句话说:它怎么知道这个API是做什么的 / 这个API是数组中的 ),要搞这个问题,就要看看在js中是怎么去调数组的API的?

试验一下:这7个API是否可以做到监视数据的效果
答案肯定不是
而上面探索的结果,在Vue官网说的有
所以:Vue中要监视到数组的变化,调用下面的7个API中的一个就可以
一定是上面的7个API中的一个才可以吗?
Vue监视数据的原理
1、text类型

2、radio单选框类型


3、checkBox多选框类型

4、select与option下拉框类型

5、textarea类型

6、checkBox的另一种类型:做协议勾选的

7、做了上面这些就可以把数据收集起来了

8、v-model的修饰符
前面说过事件的修饰符,
而v-model也有修饰符,就3个而已:number、lazy、trim,看名字大概就知道是干嘛的
(1)、number修饰符,这个修饰符一般都是和input的number类型一起使用的,如:增加一个年龄
去控制台查看,会发现一个问题
因此:需要把number弄为number类型

(2)、lazy修饰符,这个修饰符就光标离开之后再收集数据,拿textarea来举例



(3)、trim修饰符,这个在java的String中见过,再熟悉不过了,就是去除前后的空格,不演示了
9、使用v-model收集表单数据小结
回顾一下:已经学了Vue的哪些内置指令
另外还有哪些内置指令?
接下来就对上面还未见到的内置指令做一下演示和说明
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - v-text指令</title> <script src="../../js/vue.js"></script> <!-- 回顾已经学过的Vue内置指令 v-on v-bind v-model v-if、v-else-if、v-else v-show --> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <!-- 插值表达式 --> <h2> {{name}}</h2> <!-- v-text指令 这和java中的springboot推荐的thymeleaf模板中的th:text很像 --> <h2 v-text="name"></h2> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ name: '紫邪情' }, }); </script> </body> </html>


这就是插值表达式和v-text指令的最大区别,v-text是将v-text的值去找寻之后,把内容回填到对应的标签里面,是内容全覆盖,所以:例子中就算写了“信息*两个字,但是:也会被v-text值的返回内容给全覆盖了
当然:还有一个注意点


v-text内置指令小结
先说用法,其实和v-text差不多,但是内在区别很大



这里涉及到cookie的机制( 后端理解就对照玩大系统、分布式时的jwt单点登录流程原理 )
去访问一个需要输入信息的网站时( 如:要输入用户名、密码之类的重要信息 ),信息在你要登录的网站的服务器上核对成功之后,服务器返回的除了会把用户名、密码这些后续需要的东西返回回来之外,还会返回一些服务器响应的特殊json字符串,从而凭借服务器返回的这些信息,你才可以进入到相应的页面,而这些信息就保存在浏览器的cookie中,如下图:
而服务器返回的json信息有大用处,你的重要信息就保存在cookie中,比如:成功登录之后,操作其他的功能就不会要求再次输入用户名、密码之类的( 个别除外,那是另外设计机制 ),这里聪明点的就会想到另一个东西:跨浏览器不会出现无账号密码就可以访问涩,比如:我在google浏览器登录之后,再用Edge浏览器打开,那Edge是不会登录的涩,但是:利用v-html就可以做到窃取你在google浏览器中登录之后服务器给你返回的json信息,然后把这些json信息放到Edge浏览器中,那么Edge浏览器就不需要做登录操作,一样可以登录进去
而使用v-html能够获取到cookie是因为:可以在用v-html获取的内容中夹杂一些获取你当前服务器的cookie,然后拼接到窃取人的服务器地址的后面( 比如:网页中的恶意广告,那广告词中的词条是通过v-html渲染上去的,那么一点击就会把你电脑上的cookie获取到然后转发到他自己的服务器上去 )
当然:现在好一点的浏览器都为了防止xss攻击( 模拟用户之手 ),所以:对浏览器做了一些安全限定,最典型的就是google浏览器,默认是不可以携带cookie转发的,但是有些做的不好的浏览器( 网站 )就可能没弄这些,一点然后跳过去就遭殃了
v-html小结
实例
把加载js的代码移动一个位置
然后把浏览器的网速调一下
然后重新刷新页面,会发现页面的name会有一个稍微慢一点的页面加载过程,是从 {{name}} ——————> 紫邪情,这里不方便演示,就不弄了
而为了解决这个问题,可以使用v-cloak指令,本质是操作CSS罢了
v-cloak指令小结
实例




v-once指令小结
实例

v-pre小结
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - 函数式定义</title> <script src="../../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>原来的数值为: {{number}}</h2> <hr/> <!-- 使用自定义指令 --> <h2> 扩大10倍之后的数值: <span v-big = "number"/> </h2> <hr/> <button @click = "number ++"> <h4>number+1</h4></button> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ number: 10 }, // 设置自定义指令 - 函数式 // directives里面是可以写N多个自定义指令的,加了s嘛 directives: { /* element 是自定义指令所在结构的HTML标签元素( 节点 ) binding 是模板中自定义指令和HTML元素进行的绑定的信息,在这个绑定中有一些需要的东西 注:次绑定和v-bind中的绑定不是一个概念 v-bind是指的HTML元素内的"属性"和值的绑定 */ big(element , binding){ element.innerText = binding.value * 10 } } }); </script> </body> </html>


注意点:上面自定义的指令什么时候会被调用?
来个实例

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>2 - 对象式定义</title> <script src="../../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <!-- 现在做一件事情:模拟lable for标签效果 就是:光标位置锁定 别在意设计好不好--> <h2>计数: {{count}}</h2> <button @click = "count++">地址: </button> <input type="text" v-findfocus:value= "address"> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ count: 1, address: '中国大陆' }, directives: { // 先用函数式来玩一下 注意:自定义指令 多个单词别整驼峰命名啊,识别不了的 findfocus( node, binding){ console.log(node , binding); node.value = binding.value; // 获取焦点 node.focus(); } } }); </script> </body> </html>

现在再加一点要求:就是页面一初始化时,焦点就在input框中,此时发现貌似做不到( 用js可以做到啊,只是现在是用Vue ),为什么Vue不行?因为这要考虑到Vue的加载顺序问题( 重点咯,开始衍生出Vue的生命周期和钩子函数咯,也就可以很容器理解前面使用v-cloak解决页面闪烁的问题了)
所以:应该把focus()获取焦点,放到页面渲染时再做,不然:无法聚焦
相应的,用函数式并不能做到,因为:函数式直接一条龙在内存执行完了,所以:需要使用对象式自定义指令来解决这种小细节问题
update()中不写逻辑目前是不报错的,但是:最好还是写上

1、命名的坑
这个坑在前面玩对象式时已经说过了,多个单词的名字别采用驼峰命名,但是:只说了这一点,并没有说正确形式应该怎么命名
现在采用驼峰命名看一下这个坑




2、this指向的坑

为什么自定义指令中的this是window对象?
this变了,那想要拿到Vue中的数据咋办?
3、补充:自定义全局指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>4 - 全局指令配置</title> <script src="../../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>计数: {{count}}</h2> <button @click = "count++">地址: </button> <!-- 正确形式命名 采用 - 分隔开 --> <input type="text" v-find-focus:value= "address"> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 定义全局指令 - 对象式 /* 第一个参数 指令名 第二个参数 配置项( 就是把前面的对象配置{}这个花括号整体搬过来了而已 ),函数式也是一样的 只不过函数式需要使用 function给包裹起来而已 */ Vue.directive('find-focus',{ // 1、HTML元素和指令进行绑定时执行的函数 bind(node, binding){ node.value = binding.value; }, // 2、指令所在元素被插入被解析完毕,插入到页面后执行的函数 inserted(node, binding){ node.focus(); }, // 3、指令所在模板被重新解析时执行的函数 update(node, binding){ node.value = binding.value; } }) /* // 函数式全局指令 Vue.directive('find-focus', function(){ // 1、HTML元素和指令进行绑定时执行的函数 bind(node, binding){ node.value = binding.value; }, // 2、指令所在元素被插入被解析完毕,插入到页面后执行的函数 inserted(node, binding){ node.focus(); }, // 3、指令所在模板被重新解析时执行的函数 update(node, binding){ node.value = binding.value; } }) */ // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ count: 1, address: '中国大陆' }, }); </script> </body> </html>1、定义语法
(1)、局部指令
对象式 new Vue({ directives: { 指令名: { 配置 } } }) 函数式 new Vue({ directives: { 指令名(){ 配置 } } })(2)、全局配置
对象式 Vue.directive( '指令名',{ 配置 }) 函数式 Vue.directive('指令名', function(){ 配置 })配置中常用的3个回调
注意项:
做这么一个效果 —— 文本动态透明
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>1 - 认识Vue生命周期概念</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2 :>玩动态改变文本透明度</h2> {{ change() }} </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ num: 1, }, // 改变透明度值大小 methods: { change(){ setInterval(() => { if( this.num <= 0 ) this.num = 1; this.num -= 0.01; }, 50); } } }); </script> </body> </html>
改造:使用Vue的钩子函数
注意:钩子函数执行的次数问题

Vue生命周期总结
生命周期过程


先来看一下这部分

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>2 - Vue的挂载</title> <script src="../../js/vue.js"></script> </head> <body> <!-- 被 vm 实例所控制的区域 --> <div id="app"> <h2>{{name}}</h2> <button @click = "print">切换名字</button> </div> <script> // 去除浏览器控制台中的警告提示信息 Vue.config.productionTip = false; // 创建 vm 实例对象 const vm = new Vue({ // 指定控制的区域 el:'#app', data:{ name: '紫邪情' }, methods: { print(){ console.log("正在执行print()函数"); } }, // 之前只开始初始化生命周期、事件,此时:还不能使用vm访问data和methods beforeCreate () { // 操作data中的数据 methods也是差不多的 console.log( this.name ); // 查看Vue内容,看看是哪些东西 console.log(this); // 打断点 和java中的debug是一回事 debugger; } }); </script> </body> </html>
接着来看这一部分



接着看这一部分








最后来看这一部分






以上就是Vue的挂载过程

来看beforeUpdate()



接着来看Updated











以上的这些流程也是React的生命周期流程,当然:有些名字改了一下啊,而Vue就多了一个destroyed(),但是此阶段也是个极度忽略的阶段,因为没什么事做
Vue生命周期共有8个( 4对 ),另外其实还有3个周期( 但是:这三个需要到router路由中玩切换时才能整 )
beforeCreate() created() beforeMount() mounted() beforeUpdate() Updated() beforeDestroy() Destroyed()其中:常用的钩子函数就两个
关于销毁vm的问题