慕课网Vue-去哪了3
三、Vue基础讲解
1.创建实例
<body> <div id="root"> <div @click="handleClick"> {{message}} </div> <item></item> </div> <script> Vue.component('item',{ template:'<div>hellow world!</div>' })//组件也是一个个实例 var vm = new Vue({//创建实例,入口,根实例 el:'#root', //接管#root标签里面所有的dom显示 data:{ //存放数据,插值表达式显示 message:'hellow world' }, methods:{ handleClick(){ //绑定事件 alert('hello') } } }) //一个vue项目是由很多小组件组成的(是由很多vue实例组成的) </script> </body>
2.Vue实例的生命周期钩子
<body> <div id="app">hellow world </div> <script> //生命周期函数就是vue实例在某一个时间点会自动执行的函数 var vm = new Vue({ //1 el:'#app', template:"<div>{{text}}</div>", //4如果没有模板属性,自动将el对应的html元素当做模板渲染,如果有template就用模板渲染 data:{ text:"goodbye" }, beforeCreate:function(){//2创建vue实例,部分初始化后自动执行的函数 console.log('beforeCreate') }, created:function(){ //3初始化完成后执行 console.log('created') }, beforeMount:function(){ //5在模板渲染到页面上之前,执行函数 console.log(this.$el), console.log('beforeMount') }, mounted:function(){ //5模板挂在到页面之上(显示数据后),执行生命周期函数 console.log(this.$el), console.log('mounted') }, beforeDestroy:function(){ //6当实例要被销毁时( vm.$destroy() )。销毁之前执行 console.log('beforeDestroy') }, destroyed(){//7销毁之后执行, console.log('destroyed') }, beforeUpdate:function(){//7当数据发生改变,还没有重新渲染之前 console.log('beforeUpdate') }, updated:function(){//8当重新渲染之后 console.log('updated') } }) </script> </body>
输出:
goodbye
console:
3.Vue的模板语法
① 插值表达式{{ }}
<div id="app"> {{name}} </div> <script> var vm = new Vue({ //1 el:'#app', data:{ name:"Dell" } }) </script>
② v-text指令
== innertext内容
<div id="app"> <div v-text="name"></div> </div>
③v-html指令
== innerhtml
<div v-html="name"></div>
v-text == {{ }}
v-html可以识别html标签(h1),其他两种会直接转义为字符串
④ v-on: 绑定事件 ,简写 @
v-bind: 绑定数据 =>
<div id="app"> <div>{{name + 'Lee'}}</div> <div v-text="name"></div> <div v-html="name + 'Lee'" v-bind:title="name"></div> </div>
4.计算属性,方法和侦听器
①计算属性
例:显示全名
<div id="app"> {{firstName + " " + lastName}}
</div> <script> var vm = new Vue({ el:'#app', data:{ firstName:"Dell", lastName:"Lee" } }) </script>
计算属性有一个缓存机制 :该计算属性依赖的变量未发生改变时,(当其他数据改变后)计算属性就不会重新计算。一直用上一次计算的结果,提高性能
<div id="app"> {{fullName}} </div> <script> var vm = new Vue({ el:'#app', data:{ firstName:"Dell", lastName: "Lee", //fullName: "Dell Lee" //产生冗余,因为已经定义过姓和名 }, //为了不产生冗余,又把fullName显示出来 ==》计算属性 computed:{ fullName:function(){ return this.firstName+ " " +this.lastName; } } }) </script>
②还可以用一个方法的形式实现同样的功能
<body> <div id="app"> {{fullName()}} {{age}} </div> <script> var vm = new Vue({ el:'#app', data:{ firstName:"Dell", lastName: "Lee", age:28 }, methods:{ fullName(){ console.log("计算了一次"); return this.firstName+ " " +this.lastName; } } }) </script> </body>
console:
由此可见,方法并不如计算属性有效
③侦听器watch
<body> <div id="app"> {{fullName}} {{age}} </div> <script> var vm = new Vue({ el:'#app', data:{ firstName:"Dell", lastName: "Lee", fullName: "Dell Lee", //产生冗余,因为已经定义过姓和名 age:28 }, //为了不产生冗余,又把fullName显示出来 ==》计算属性 // computed:{ // fullName:function(){ // return this.firstName+ " " +this.lastName; // } // } //方法 // methods:{ // fullName(){ // console.log("计算了一次"); // return this.firstName+ " " +this.lastName; // } // } //侦听器 watch:{//当 firstname改变时执行 firstName:function(){ this.fullName = this.firstName+ " "+this.lastName; }, lastName:function(){ this.fullName = this.firstName+ " "+this.lastName; } } }) </script> </body>
watch 和 computed 都具有缓存机制,且相对而言,wach的代码程度比computed要复杂。
所以当一个功能同时可以用computed、methods和watch实现时,优先推荐 computed
5. 计算属性的getter和setter
<body> <div id="app"> {{fullName}} {{age}} </div> <script> var vm = new Vue({ el:'#app', data:{ firstName:"Dell", lastName: "Lee", age:28 }, computed:{ // fullName:function(){ // return this.firstName+ " " +this.lastName; // }//等于get //写成对象 fullName:{ get:function(){ return this.firstName+ " " +this.lastName; },//取值 set:function(value){//(fullName发生改变)接收外部传入的value console.log(value); var arr = value.split(" ");//以空格分割字符串 this.firstName = arr[0]; this.lastName = arr[1] }//设置值 } } }) </script> </body>
上一节使用的computed方法就是get。
当set设置fullName时,firstName发生变化,且firstName是fullName依赖的值,就会引起fullName的重新计算。
总结:
get:当fullName依赖的数据发生变化时,重新计算显示
set:当fullName设置后,set业务代码执行,间接使fullName依赖的数据改变,从而重新计算fullName显示。
6. Vue中的样式绑定
vue是面向数据开发,并不直接操作dom,如何将数据和样式关联,数据改变样式就改变:
① class对象绑定
<body> <div id="app"> <div @click="handleDivClick" :class="{activated: isActivated} " > hello world</div> </div> <script> var vm = new Vue({ el:'#app', data:{ isActivated: false }, methods:{ handleDivClick(){ this.isActivated = !this.isActivated } } }) </script> <style> .activated{ color: red; } </style> </body>
②class数组绑定
<div id="app"> <div @click="handleDivClick" :class="[activated] " > hello world</div> </div> <script> var vm = new Vue({ el:'#app', data:{ activated:'' }, methods:{ handleDivClick(){ this.activated= this.activated==="activated"?" ":"activated" } } }) </script>
③ style 对象绑定
:style="styleObj"
<div id="app"> <div @click="handleDivClick" :style="styleObj" > hello world</div> </div> <script> var vm = new Vue({ el:'#app', data:{ styleObj:{ color:"black" } }, methods:{ handleDivClick(){ this.styleObj.color= this.styleObj.color==="black"? "red ":"black" } } }) </script>
④style数组绑定
<body> <div id="app"> <div @click="handleDivClick" :style="[styleObj,{fontSize:'20px'}]" > hello world</div> </div> <script> var vm = new Vue({ el:'#app', data:{ styleObj:{ color:"black" } }, methods:{ handleDivClick(){ this.styleObj.color= this.styleObj.color==="black"? "red ":"black" } } }) </script> <style> .activated{ color: red; } </style> </body>
7.Vue 条件渲染
v-if指令:返回值true、false决定了当前div是否挂载到页面
比较:v-if和v-show都可以控制一个模板标签是否在页面上显示
当返回值为false时,v-if 是直接不显示在dom元素上,而v-show是给当前div添加dislay:none;属性
在使用上,如果一个页面上dom元素有频繁的显示隐藏操作,建议用v-show,因为它不会(像v-if)频繁的把一个dom删除添加
<body> <div id="app"> <div v-if ="show" >{{message}}</div> <div v-show ="false" >{{message}}</div> </div> <script> var vm = new Vue({ el:'#app', data:{ show:true, message:"hello world", false:false }, methods:{ } }) </script> </body>
结合v-else使用,当v-if为false时执行else
<div id="app"> <div v-if ="show" >{{message}}</div> <div v-else>Bye World</div> </div>
if和else要紧贴使用,两者之间不能有其他元素标签,否则报错
代码加工:
<body> <div id="app"> <div v-if ="show === 'a'" >This is A</div> <div v-else-if ="show === 'b'" >This is B</div> <div v-else>Bye World</div> </div> <script> var vm = new Vue({ el:'#app', data:{ show:'a', } }) </script> </body>
②关键字 key
当给某个元素标签加上key值后,Vue会知道它是页面上唯一的元素。
如果两个相同的元素key值不一样,vue就不会去尝试复用以前的input标签
源码:
<body> <div id="app"> <div v-if ="show" >用户名:<input kye="username"/></div> <div v-else>邮箱:<input key="useremail"/></div> </div> <script> var vm = new Vue({ el:'#app', data:{ show:false, } }) </script> </body>
示例:
有key:
没有key:
8. Vue中的列表渲染
v-for列表遍历
<body> <div id="app"> <div v-for="item of list"> {{item}} </div> </div> <scripat> var vm = new Vue({ el:'#app', data:{ list:[ "hello", "dell", "nice", "to", "meet", "you" ] } }) </script> </body>
问题一:
数组的默认参数index:数组中每一项的索引下标
<body> <div id="app"> <div v-for="(item,index) of list"> {{item}}---{{index}} </div> </div> <scripat> var vm = new Vue({ el:'#app', data:{ list:[ "hello", "dell", "nice", "to", "meet", "you" ] } }) </script> </body>
问题二:
为了提升循环显示的性能,会给每一个循环项上加上一个唯一的key。
key值并不推荐用index,在频繁操dom元素相对应的数据时,比较费性能,让vue不能充分复用dom节点。
一般后端返回数据时,会有和数据条目对应的唯一的数据符(id)
<body> <div id="app"> <div v-for="(item,index) of list" :key="item.id"> {{item.text}}---{{index}} </div> </div> <script> var vm = new Vue({ el:'#app', data:{ list:[ { id:"0000000111", text:"hello" },{ id:"0000000112", text:"world" } ] // list:[ // "hello", // "dell", // ] } }) </script> </body>
输出:
hello---0
world---1
问题三: 数组添加删除(七个变异方法)
vm.list.push({id:"001",text :"1"}) √
vm.list[3] = {id:"001",text :"1"} ×
push --- 最后一项后添加
pop --- 最后一项后删除
shift -- 数组第一项删除
unshift -- 数组第一项前加
splice --- 数组截取
sort --- 数组排序
reverse --- 取反
例子:替换
vm.list.splice(从下标开始,处理长度,内容)
vm.list.splice(1,1,{id:"001",text :"1"} ) √
输出:
<body> <div id="app"> <template v-for="(item,index) of list" :key="item.id"> <div > {{item.text}}---{{index}} </div> <span> {{item.text}}</span> </template> </div> <script> var vm = new Vue({ el:'#app', data:{ list:[ { id:"0000000111", text:"hello" },{ id:"0000000112", text:"world" } ] // list:[ // "hello", // "dell", // ] } }) </script> </body>
输出:
但是有一个小问题:Vue不支持在 template 元素上绑定属性。
比如这里想绑定 key 属性就不行。会报错。
解决方法:可以改成div (会被渲染)或者 不使用template元素做for循环(新建一个div做两个for循环,会冗余)
问题五:对象循环
循环展示对象内容
<body> <div id="app"> <div v-for="(item,key,index) of userInfo" > {{item}}---{{key}}----{{index}} </div> </div> <script> var vm = new Vue({ el:'#app', data:{ userInfo:{ name:"Dell", age:25, gender:"male", salary:"secret" } } }) </script> </body>
对象额外能接收参数key,表键名
输出:
问题五:对象修改
vm.userInfo.name = ”Dell Lee“ √
对象添加:
vm.userInfo.address= "BeiJing" × (数据虽然变了,但是页面上依然是4条)
实现: 类似数组那样直接改引用
vm.userInfo={
} √ 数据发生变化,页面同时变化
9. Vue中的set方法
除了上节讲到直接改引用的方式添加对象数据之外,Vue还提供了一种set方法
通过Vue.set方法向一个对象中增加值,vm.userInfo 中就会多出来address这个值,而且数据变了后页面会跟着联动
① set既是Vue上的一个全局方法,可以用以修改对象。
又是vue的实例方法
通过vue实例的$set方法,也可以实现一样的效果
② 数组上的set方法使用
给数组添加数据:
回顾上文的两个方法
- =》数组的7个变异方法(push、pop等等)
- =》改变数组的引用
第三种 set方法:
前面有说,如果想修改数组中某一项的内容,通过直接修改数组的方式(vm.userInfo[1]= ..),
数据虽然改变了,但是页面并不会跟着变化。
Vue.set就是解决这个问题
<body> <div id="app"> <div v-for="(item,index) of userInfo" > {{item.text}} -{{index}} </div> </div> <script> var vm = new Vue({ el:'#app', data:{ userInfo:[ { id:"0000000111", text:"hello" },{ id:"0000000112", text:"world" } ] } }) </script> </body>
console:
同样:使用vue实例的$set方法也是可以的 == 例:vm.$set(vm.userInfo,1,{id:"0000000112",text:"Dell world"})
总结:
数组改变,页面改变:
改变数组的引用。调数组的变异方法。使用vue中set方法。
对象改变,页面改变:
改变对象的引用。使用vue中set方法