vue核心
vue的特点
采用组件化模式,提高代码复用率,且让代码更好维护
声明式编码,让编码人员无需直接操作DOM,提高开发效率
使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
helloworld的一个小案例
1)想让vue工作,就必须创建一个vue案例,且要传入一个配置对象
2)root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法
3)root容器里的代码被称为vue模板
4)vue实例和容器是一一对应的
5)真实开发中只有一个vue实例,并且会配合着组件一起使用
6){{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
7)一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h1>{{name}}之道</h1> </div> <script type="text/javascript"> const x = new Vue({ el:'#root', data:{ name:'学习' } }) </script> </body> </html>
模板语法
1.插值语法
功能:用于解析标签体内容
写法:{{xxx}}, xxx是js表达式,且可以直接读取到data中的所有属性
2.指令语法
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)
举例:v-bind:href="xxx" 或简写为: :href="xxx" xxx同样要写js表达式,且可以直接读取到data中的所有属性
数据绑定
1.单向绑定: 数据只能从data流向页面
2.双向绑定:数据不仅能从data流向页面,还可以从页面流向data
备注:双向绑定一般都应用在表单类元素上
v-model:value 可以简写为 v-model 因为v-model默认收集的就是value值
el的两种写法
data的两种写法
1).对象式
2).函数式
如何选择:目前哪种都可以,但是到了使用组件的阶段,data必须使用函数式,否则会报错
3)一个重要的原则,由vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是vue实例了
MVVM 模型
M:模型(Model)对应data中的数据
V:视图(View) 模板
VM:视图模型(ViewModel): Vue实例对象
数据代理
数据代理:就是将数据交由Object.defineProperty(Person,'age')
如下例子中,当有需求获取age属性时,就会调用get()方法,当我们想要修改age的大小时,直接给其赋值,根据所写的set()方法,会直接将值赋给number,之后如果想要再获取age值,就再调用get方法获取number
例子如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <script type="text/javascript"> let number = 18 let person = { name:'张三', sex:'男', } Object.defineProperty(person,'age',{ get(){ console.log('有人读取age属性了') return number }, set(value){ console.log('有人修改了age属性,并且值为',value) number = value } }) </script> </body> </html>
事件的基本使用
1)使用v-on:xxx 或者xxx 绑定事件 其中xxx是事件名
2)事件的回调需要配置在methods对象中,最终会在vm上
3)methods中配置的函数,不要用箭头函数!否则this就不是vm了
4)methods中配置的函数,都是被vue所管理的函数,this的指向是vm或组件实例对象
5)@click=“demo” 和 @click=“demo($event)” 效果一致,后者可以传参
事件修饰符
1)prevent 阻止默认事件 (常用)
2)stop 阻止事件冒泡 (常用)
3)once: 事件只触发一次 (常用)
4)capture: 使用事件的捕获模式
5)self: 只有event.target是当前操作的元素才是触发事件
6)passive:事件的默认行为立即执行,无需等待事件回调执行完毕
例子如下,只举例了常用的
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <style> *{ margin-top: 20px; } .demo1{ height: 50; background-color: aqua; } </style> <body> <div id="root"> <h2>欢迎来到{{name}}学院</h2> <a href="http://www.baidu.com" @click.prevent="showInfo()">点我提示信息</a> <div class="demo1" @click="showInfo()"> <button @click.stop="showInfo()">点我提示信息</button> </div> <button @click.once="showInfo()">点我提示信息</button> </div> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'gubi' }, methods:{ showInfo(e){ //e.stopPropagation() //e.preventDefault() alert('hello') } } }) </script> </body> </html>
键盘事件
vue中常见的按键别名:
回车 => enter
删除 => delete
退出 => esc
空格 => space
换行 => tab
上 => up
下 => down
左 => left
右 => right
vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转化为kebab-case(短横线命名)
系统修饰键(用法特殊) ctrl、alt、shift、meta
配合keyup使用 按下修饰按键的同时,再按下其他键,随后释放其他键,事件才被触发
配合keydown使用,正常触发事件
也可以使用keyCode去指定具体的按键(不推荐)
Vue.config.keyCodes.自定义键名 = 键码, 可以去定制按键别名
举例(按下回车提示信息)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo()"> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'gubi' }, methods:{ showInfo(e){ //e.stopPropagation() //e.preventDefault() alert('hello') } } }) </script> </html>
组合键的使用方式:
姓名案例
插值语法实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> 姓: <input type="text" v-model="firstname"> <br/><br/> 名: <input type="text" v-model="lastname"> <br/><br/> 全名: <span>{{firstname}}-{{lastname}}</span> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ firstname:'张', lastname:'三', } }) </script> </html>
methods实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> 姓: <input type="text" v-model="firstname"> <br/><br/> 名: <input type="text" v-model="lastname"> <br/><br/> 全名: <span>{{fullname()}}</span> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ firstname:'张', lastname:'三', }, methods: { fullname(){ return this.firstname+'-'+this.lastname } } }) </script> </html>
计算属性实现
1)定义:要用的属性不存在,要通过已有属性计算得来
2)原理:底层借助了Object.defineproperty方法提供的getter和setter
3)get函数什么时候执行?
初次读取时会执行一次(接下来如果数据没有改变就不会再执行,因为有缓存)
当依赖的数据发生改变时会被再次调用
4)优势:与methods相比,内部有缓存机制(复用)效率更高,调试方便
5)备注:
计算属性最终会出现在vm上,直接读取使用即可
如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> 姓: <input type="text" v-model="firstname"> <br/><br/> 名: <input type="text" v-model="lastname"> <br/><br/> 全名: <span>{{fullname}}</span> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ firstname:'张', lastname:'三', }, computed:{ fullname:{ get(){ return this.firstname+'-'+this.lastname }, set(value){ console.log('set',value) const arr = value.split('-') this.firstname=arr[0]; this.lastname=arr[1]; } } } }) </script> </html>
监视属性
1)当被监视的属性变化时,回调函数自动调用,进行相关操作
2)监视的属性必须存在,才能进行监视
3)监视的两种写法(以下代码中有)
通过.new Vue时传入watch配置
通过vm.$watch监视
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id=root> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ isHot:true }, computed:{ info(){ return this.isHot ? '炎热' : '凉爽' } }, methods:{ changeWeather(){ this.isHot=!this.isHot } }, //写法1 /* watch:{ isHot:{ handler(newValue,oldValue){ console.log('ishot被修改了',newValue,oldValue) } } } */ }) //写法2, 适用于一开始不知道要监视的对象,后来才得知然后补上的情况 vm.$watch('isHot',{ handler(newValue,oldValue){ console.log('ishot被修改了',newValue,oldValue) } }) </script> </html>
深度监视
1)vue中的watch默认不监测对象内部值的改变 (一层)
2)配置deep:true可以监测对象内布置改变(多层)
computed和watch之间的区别
1)computed能完成的功能,watch都可以完成
2)watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作,但是computed不行
两个重要的小原则
1)所被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
2)所有不被vue所管理的函数(定时器的回调函数,ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象
绑定样式
我们在进行开发的时候,如果不用vue的话,免不了直接操作dom对象,vue给了我们一种间接操作dom对象的方法
如下代码中,使用了三种间接操作dom对象并且给其赋予样式的方式,各有优劣
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .basic{ width: 400px; height: 100px; border: 1px solid black } .tmp1{ background-color: red; } .tmp2{ background-color: green; } .tmp3{ background-color: black; } </style> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 --> <div class="basic" :class="mood" @Click="changeMood">test</div> <!-- 绑定class样式--数组写法, 适用于:要绑定的样式个数不确定、名字不确定 --> <div class="basic" :class="classArr">test</div> <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定,名字也确定,但要动态决定是否使用 --> <div class="basic" :class="classObj">test</div> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ mood:'tmp1', classArr:['tmp1','tmp2'], classObj:{ tmp1:false, tmp2:false, tmp3:false } }, methods:{ changeMood(){ const arr = ['tmp1','tmp2','tmp3'] const index = Math.floor(Math.random()*3) this.mood=arr[index] } } }) </script> </html>
条件渲染
v-if
1)v-if=“表达式”
2)v-else-if="表达式"
3)v-else="表达式
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除
注意::v-if可以和:v-else-if、 v-else 一起使用,但要求结构不能被“打断”
v-show
写法:v-show="表达式"
适用于:切换频率较高的场景
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
注意:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2 v-show="flag">{{name}},欢迎您</h2> <h2>当前的n值时:{{n}}</h2> <button @click="n++">点我n+1</button> <div v-if="n===1">hah</div> <div v-else-if="n===2">huh</div> <div v-else-if="n===3">xix</div> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ name:'gubi', flag:true, n:0 } }) </script> </html>
列表渲染
v-for 指令
1)用于展示列表数据
2)语法:v-for="(item,index) in xxx" :key="yyy"
3) 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
key的作用与原理
1)虚拟DOM中key的作用
key是虚拟dom对象的标识,当状态中的数据发生变化时,vue会根据新数据生成新的虚拟dom,随后vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下
2)对比规则:
1)旧虚拟dom中找到了与新虚拟DOM相同的key
若虚拟dom中内容没变,直接使用之前的真是dom
若虚拟dom中内容变了,则生成新的真是DOM,随后替换掉页面中之前的真实DOM
2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面
3)用index作为key可能引发的问题
1)若对数据进行:逆序添加,逆序删除等破环顺序的操作,会产生没有必要的真实DOM更新==> 页面效果没问题,但效率低
2)如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
4)开发中如何选择key
1)最好使用每条数据的唯一标识作为key,比如id
2)如果不存在对数据的逆序添加,逆序删除等破坏顺序的操作,仅用于渲染列表展示,那么用index时没有问题的
列表过滤
想要实现列表过滤,可以通过监听和计算
举个例子:如下,我们进行关键字查询来过滤出条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <input type="text" placeholder="请输出名字" v-model="keyWord"/> <ul> <li v-for="p in filpersons"> {{p.name}}-{{p.age}} </li> </ul> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ keyWord:'', persons:[ {id:'001',name:'马冬梅',age:18,sex:'女'}, {id:'001',name:'周冬雨',age:19,sex:'女'}, {id:'001',name:'周杰伦',age:20,sex:'男'}, {id:'001',name:'温兆伦',age:20,sex:'男'} ], filpersons:[] }, /* 方式一 监听*/ watch:{ keyWord:{ immediate:true, handler(val){ this.filpersons=this.persons.filter((p)=>{ return p.name.indexOf(val) !=-1 }) } } } /* 方式二 计算属性 */ /* computed:{ filpersons(){ return this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord) !== -1 }) } } */ }) </script> </html>
vue数据监测原理
1)vue监视data中所有层次的数据
2)如何监测对象中的数据?
通过setter实现监视,且要再new Vue时就传入要监测的数据
1)对象中后追加的属性,vue默认不做响应式处理
2)如需给后添加的属性做响应式,请使用如下API
Vue.set(target,propertyName/index, value) 或
vm.$set(target,propertyName/index, value)
3)如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事
1)通过原生对应的方法对数组进行更新
2)重新解析模板,进而更新页面
4)在vue修改数组中的某个元素时,一定要用如下方法
1)使用API push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2)Vue.set()或vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm或vm的根数据对象添加属性!
例子如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h1>学生信息</h1> <button @click="addSex">添加性别属性,默认值:男</button> <button @click="addFriend">在列表首位添加一个朋友</button> <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <button @click="addHobby">添加一个爱好</button> <button @click="updateHobby">修改第一个爱好为开车</button> <h3>姓名:{{student.name}}</h3> <h3>年龄:{{student.age}}</h3> <h3>年龄:{{student.sex}}</h3> <h3>爱好</h3> <ul> <li v-for="(h,index) in student.hobby" :key=index> {{h}} </li> </ul> <h3>朋友们</h3> <<ul> <li v-for="(f,index) in student.friends" :key=index> {{f.name}}--{{f.age}} </li> </ul> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ student:{ name:'tom', age:18, hobby:['抽烟','喝酒','烫头'], friends:[ {name:'jerry',age:35}, {name:'tony',age:36} ] } }, methods:{ addSex(){ //这种写法vue不认 //this.student.sex='男' Vue.set(this.student,'sex','男') }, addFriend(){ this.student.friends.unshift({name:'jack',age:70}) }, updateFirstFriendName(){ this.student.friends[0].name='张三' }, addHobby(){ this.student.hobby.push('学习') }, updateHobby(){ //这句话意思为,删除第0个,然后插入一个新的,叫开车 this.student.hobby.splice(0,1,'开车') } } }) </script> </html>
收集表单数据
若 <input type="text" /> 则v-model收集的就是value值,用户输入的就是value值
若 <input type="radio" /> 则v-model收集的就是value值,且要给标签配置value值
若 <input type="checkbox"/>
1)没有配置input的value属性,那么收集的就是checked (布尔值)
2)配置input的value值
如果v-model的初始值是非数组,那么收集的是checked
如果v-model的初始值是数组,那么收集的就是value值
v-model的三个修饰符
lazy: 失去焦点时再收集数据
number: 输入字符串转为有效的数字
trim: 输入首位空格过滤
过滤器 (没有进行实操,视频在P39)
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
语法:
1)注册过滤器 Vue.filter(name,callback) 或 new Vue{filters:{}}
2)使用过滤器: {{xxx | 过滤器名 }} 或 v-bind: 属性 = “xxx | 过滤器名”
备注:
1)过滤器可以接受额外参数,多个过滤器也可以串联
2)并没有改变原本的数据,是产生新的对应数据
内置指令
我们在这之前学过的指令有
v-bind: 单向绑定解析表达式
v-model: 双向数据绑定
v-for: 遍历
v-on: 绑定事件监听,可以简写为@
v-if: 条件渲染语句
v-else: 条件渲染语句
v-show: 条件渲染语句
接下来我们要学习的指令
v-text
作用:向其所在的节点中渲染文本内容
与插值语法的区别: v-text会替换掉节点中的内容 {{xxx}}则不会
不能解析html语法
例子如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <!-- 这一种比较灵活 --> <div>{{name}}</div> <br/> <!-- v-text这一指令用起来没有上面这一种顺手 --> <div v-text="name">你好</div> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'gubi' } }) </script> </html>
v-html
作用:能够解析html语法
与插值语法的区别:
v-html会替换掉节点中的内容 {{xxx}}则不会
可以识别html结构
严重注意:v-html有安全性问题
在网站上动态渲染任意HTML是非常危险的,容易导致X
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <!-- 这一种比较灵活 --> <div>{{name}}</div> <br/> <!-- v-text这一指令用起来没有上面这一种顺手 --> <div v-html="str">你好</div> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'gubi', str:'<h3>你好啊!</h3>' } }) </script> </html>
v-cloak
本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once
v-once所在节点再初次动态渲染后,就视为静态内容了
以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2 v-once>初始化的n值是:{{n}}</h2> <h2>当前的n值是:{{n}}</h2> <button @click="n++">click me n++</button> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ n:1 } }) </script> </html>
v-pre
跳过其所在节点的编译过程
可利用它跳过:没有指令语法、没有使用插值语法的节点,会加快编译
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2 v-pre>hahah,这里就适合用v-pre来加快编译</h2> <h2 v-once>初始化的n值是:{{n}}</h2> <h2>当前的n值是:{{n}}</h2> <button @click="n++">click me n++</button> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ n:1 } }) </script> </html>
自定义指令
需求1:定义一个v-big指令,将绑定的数据10倍呈现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2>当前的n值为:{{n}}</h2> <h2>放大10倍后的n值为:<span v-big="n"> </span> </h2> <button @click="n++">click me n++</button> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ n:1 }, directives:{ big(element,binding){ element.innerText=binding.value*10 } } }) </script> </html>
big函数何时会被调用?
1)指令与元素成功绑定时
2)指令所在的模板被重新解析时
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点(在此例子中,只能用对象式,因为焦点这种细节问题函数式无法解决)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2>当前的n值为:{{n}}</h2> <h2>放大10倍后的n值为:<span v-big="n"> </span> </h2> <input type="text" v-fbind:value="n"> <button @click="n++">click me n++</button> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ n:1 }, directives:{ big(element,binding){ element.innerText=binding.value*10 }, /* fbind(element,binding){ element.value=binding.value*10 } */ fbind:{ bind(element,binding){ console.log('fbind',this) //注意,指令的对象时window element.value=binding.value console.log('bind') }, inserted(element,binding){ element.focus() console.log('inserted') }, update(element,binding){ element.value=binding.value console.log('update') } } } }) </script> </html>
语法总结:
一、定义语法:
二、配置对象中常用的3个回调
1)bind:指令与元素成功绑定时调用
2)inserted 指令所在元素被插入页面时调用
3)update 指令所在模板结构被重新解析时调用
三、备注
1)指令定义时不加v-,但使用时要加v-
2)指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
生命周期
1)又名:生命周期回调函数,生命周期函数,生命周期钩子
2)是什么:vue在关键时刻帮我们调用的一些特殊名称的函数
3)生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
4)生命周期函数中的this指向是vm或组件实例对象
举个例子,让一段话出现一种从实体到透明到实体的循环过程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="root"> <h2 :style="{opacity}">gubi加油</h2> </div> </body> <script type="text/javascript"> const vm = new Vue({ el:'#root', data:{ opacity:1 }, //vue完成模板的解析并把初始的真实dom元素放入页面后调用mounted mounted(){ console.log('mouted') setInterval(()=>{ this.opacity -= 0.01 if(this.opacity <= 0) this.opacity = 1 },16) } }) </script> </html>
这个例子当中涉及了一个函数 mounted() 这就是生命周期当中的其中一个函数
1)beforeCreate 初始化生命周期、事件,但数据代理还未开始,此时,无法通过vm访问到data中的数据,methods中的方法
2)created 初始化数据监测、数据代理,可以通过vm访问到data中的数据,methods中配置的方法
3)beforeMount 页面呈现的是未经vue编译的dom结构,所有对dom的操作,最终都不奏效
4)mounted 页面中呈现的是经过vue编译的DOM 对DOM的操作均有效,至此初始化过程结束,一般会在这个阶段进行如下操作:开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作
5)beforeUpdate 此时数据是新的,但页面是旧的,即:页面尚未和数据保持同步
6)update 此时数据是新的,页面也是新的,即:页面和数据保持同步
7)beforeDestory 此时vm中所有的 data、methods、指令等等,都处于可用状态,马上要执行销毁过程,一般在此阶段:关闭定时器,取消订阅消息、解除自定义事件等收尾操作
8)destory
常用的生命周期钩子:
1)mounted 发送ajax请求、启动定时器,绑定自定义事件、订阅消息等初始化操作
2)beforeDestory 清除定时器,解绑自定义事件,取消订阅消息等收尾工作
关于销毁vue实例
1)销毁后借助vue开发者工具看不到任何信息
2)销毁后自定义事件会失效,但原生DOM事件依然有效
3)一般不会在beforeDestory阶段操作数据,因为i即使操作了数据,也不会再触发更新流程了