Vue全家桶--04 Vue.js 核心技术
Vue全家桶--04 Vue.js 核心技术
4.1 Vue入门开发
4.1.1 VS Code创建工程
4.1.2 创建HTML和安装Vue
npm instal vue@2.6.10
4.1.3 编写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>Document</title> </head> <body> <div id="app"> <!--{{}} 用于标签体内显示数据 --> hello,{{ msg }}<br/> <!--v-model进行数据的双向绑定--> <input type="text" v-model="msg" /> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el:'#app',//指定被Vue管理的入口,值为选择器,不可以指定body或者html data:{ //用于初始化数据,在Vue实例管理的Dom节点下,可通过模板请求语法来引用 msg:"vue.js" } }); </script> </body> </html>
4.2 MVVM模型
什么是MVVM模型?
MVVM:Model--View--ViewModel,一种软件架构的风格
*Model----模型,数据对象,(data中的属性)
*View----视图,模板页面,用于渲染
*ViewModel----视图模型,本质上就是Vue实例
**核心思想:通过数据驱动视图!!!
**把需要改变视图的数据初始化到Vue中,然后再通过修改Vue中的数据,从而实现对视图的更新
**声明式编程----按照Vue的特定语法进行声明开发,就可以实现对应功能,不需要我们直接操作Dom元素
**命令式编程----类似Jquery,需要手动去操作Dom才能实现对应功能
4.3 Vue Devtools插件
Vue Devtools插件安装,谷歌浏览器
4.4 模板数据绑定渲染
4.4.1 双大括号语法{{}}
格式:{{ 表达式 }}
作用:使用在标签体中,用于获取数据;可以使用JS表达式
<!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>Document</title> </head> <body> <div id="app"> <h3>双大括号</h3> <p>{{ msg }}</p> <p>{{ num + 1 }}</p> <input type="text" v-model="num" > </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm=new Vue({ el:'#app', data:{ msg:'hello', num:1 } }); </script> </body> </html>
4.4.2 一次性插值 v-once
通过使用 v-once 指令,也可以执行一次性的插值,当数据改变时,插值处的内容不会更新。
<body> <div id="app"> <h3>v-once 一次性插值</h3> <p>{{ msg }}</p> <p v-once>{{ msg }}</p> <input type="text" v-model="msg" > </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm=new Vue({ el:'#app', data:{ msg:'hello' } }); </script> </body>
4.4.3 输出HTML指令 v-html
格式:v-html='xxx'
作用:如果是HTML格式数据,双大括号会将数据解释为普通文本,为了输出真正的HTML,你需要使用v-html指令。
Vue为了防止XSS攻击,在此指令上做了安全处理,当发现输出内容有script标签时,则不渲染。
****XSS攻击主要利用JS脚本注入到网页中,读取Cookie值(Cookie一般存储了登录身份信息),读取到了发生到黑客服务器,从而黑客可以使用你的账户做非法操作;XSS攻击还可以在你进入到支付时,跳转到钓鱼网站。
<body> <div id="app"> <h3>3.指令输出真正的 HTML 内容 v-html</h3> {{contentHtml}} <!-- v-html: 1.如果输出的内容是html数据,双大括号讲数据以普通文本方式进行输出, 为了输出真正html的效果,就需要使用v-html指定 2.为了防止 XSS攻击 --> <p v-html='contentHtml'></p> <p v-html='contenthtml2'></p> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm=new Vue({ el:'#app', data:{ msg:'hello', contentHtml:"<span style='color:red'>123</span>", contenthtml2:`<span style='color:blue'>123 <script>alert('12');<\/script> </span>` } }); </script> </body>
4.4.4 v-bind 元素绑定指令
完整格式:v-bind:元素的属性名='xxxx'
缩写格式: :元素的属性名='xxx'
作用:将数据动态绑定到指定的元素上
<body> <div id="app"> <h3>4.元素绑定指令 v-bind</h3> <img style="width: 250px; height:120px;" v-bind:src="imgUrl" alt=""> <img style="width: 250px; height:120px;" :src="imgUrl" alt=""> <a :href="baiduUrl" target="_blank" >跳转</a> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm=new Vue({ el:'#app', data:{ msg:'hello', contentHtml:"<span style='color:red'>123</span>", contenthtml2:`<span style='color:blue'>123 <script>alert('12');<\/script> </span>`, imgUrl:'https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM', baiduUrl:'https://www.baidu.com' } }); </script> </body>
4.4.5 v-on 事件绑定指令
完整格式:v-on:事件名称='事件处理函数名'
缩写格式:@事件名称="事件处理函数名" 注意:@后面没有冒号
作用:用于监听DOM事件
<body> <div id="app"> <h3>5.v-on 事件绑定</h3> <input type="text" v-model='calcute'> <button v-on:click="add">点击+1</button> <button @click="add2(12)">点击+2</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: 'hello', contentHtml: "<span style='color:red'>123</span>", contenthtml2: `<span style='color:blue'>123 <script>alert('12');<\/script> </span>`, imgUrl: 'https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM', baiduUrl: 'https://www.baidu.com', calcute: 10 }, methods: { add: function () { this.calcute = this.calcute + 1; return this.calcute; }, add2: function (value) { this.calcute = this.calcute + value - 0; return this.calcute; } } }); </script> </body>
4.5 计算属性和监听器
4.5.1 计算属性 computed
computed选项定义计算属性
计算属性类似于methods选择中定义的函数,区别:
**计算属性 会进行缓存,只在相关响应式依赖发生改变时它们才会重新求值
**函数 每次都会执行函数体进行计算
<body> <div id="app"> <h3> 计算属性和监听器 </h3> chinese: <input type="text" v-model="chinesescore"> <br /> english: <input type="text" v-model="englishscore"> <br /> <!-- v-model 调用函数时,不能少了() --> total: <input type="text" v-model="add()"><br> <!-- v-model 调用计算属性时 不需要(),因为它是个属性 --> total(computed): <input type="text" v-model="sum"><br> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { chinesescore: 90, englishscore: 98 }, methods: { add: function () { var total = (this.chinesescore - 0) + (this.englishscore - 0); return total; } }, computed:{ sum:function(){ var total = (this.chinesescore - 0) + (this.englishscore - 0); return total; } } }); </script> </body>
4.5.2 计算属性(双向绑定)
计算属性默认只有getter,不过需要时可以提供一个setter,可以实现双向绑定
<body> <div id="app"> <h3> 计算属性和监听器 </h3> chinese: <input type="text" v-model="chinesescore"> <br /> english: <input type="text" v-model="englishscore"> <br /> <!-- v-model 调用函数时,不能少了() --> total: <input type="text" v-model="add()"><br> <!-- v-model 调用计算属性时 不需要(),因为它是个属性 --> total(computed): <input type="text" v-model="sum"><br> total(computed get/set): <input type="text" v-model="sum2" name="" id=""> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { chinesescore: 90, englishscore: 98 }, methods: { add: function () { var total = (this.chinesescore - 0) + (this.englishscore - 0); return total; } }, computed:{ sum:function(){ var total = (this.chinesescore - 0) + (this.englishscore - 0); return total; }, sum2:{ get:function(){ console.log("计算属性 sum2.get 被调用!"); return (this.chinesescore - 0) + (this.englishscore - 0); }, set:function(newvalue){ console.log("计算属性 sum2.set 被调用!"); var avg = newvalue / 2; this.chinesescore = avg; this.englishscore = avg; } } } }); </script> </body>
4.5.3 监听器 watch
**当属性数据发生变化时,对应属性的回调函数会自动调用,在函数内部进行计算
**通过watch选项或者vm实例的$watch()来监听指定的属性
<body> <div id="app"> chinese: <input type="text" v-model="chinesescore"> <br /> englist: <input type="text" v-model="englishscore"> <br /> 总分(监听器):<input type="text" v-model="sumScore3"><br> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { chinesescore: 89, englishscore: 88, sumScore3: 177 }, watch: { chinesescore: function (newvalue, oldvalue) { this.sumScore3 = (newvalue - 0) + (this.englishscore - 0) } } }); vm.$watch('englishscore', function (newvalue) { this.sumScore3 = (newvalue - 0) + (this.chinesescore - 0) }); </script> </body>
4.6 Class与Style v-bind 绑定
***v-bind 单向绑定!只有数据更改了,视图才会更改!视图更改了,数据是不会更改的!双向绑定是可以的都会更改!
通过 class 列表和 style 指定样式是数据绑定的一个常见需求。它们都是元素的属性,都用 v-bind 处理,其中表达
式结果的类型可以是:字符串,对象或者数组。
语法格式:v-bind:class='表达式' 或 :class='表达式' / v-bind:style='表达式' 或 :style='表达式'
*class的表达式可以为:
字符串---- :class="activeClass"
对象---- :class="{active:isActive,error:hasError}"
数组---- :class="['active','error']" 注意这里要加上单引号,不然是获取data中的值
*style的表达式一般为对象
:style="{color:activeColor,fontSize:fontSize+'px'}"
注意:对象中的value值activeColor和fontSize是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>Document</title> <style> .active { color: green; } .delete { background-color: aqua; } .error { font-size: 35px; } </style> </head> <body> <div id="app"> <h3>class绑定,v-bind:class或者:class</h3> <p v-bind:class="aciveClass">字符串表达式</p> <!-- key值是样式名,value是data中的属性值,为true渲染 --> <p :class="{delete:isDel,error:isErr}">对象表达式</p> <p :class="['active','delete','error']">数组表达式</p> <h3 :style="{color: activrColor}">style绑定 v-bind:style或者:style</h3> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { aciveClass: 'active', isDel: true, isErr: false, activrColor:'blue' } }); </script> </body> </html>
4.7 条件渲染 v-if
4.7.1 v-if 是否渲染当前元素
v-else-if
v-else
**v-show与v-if 类似,v-show只是元素始终会被渲染并保留在DOM中,通过切换元素的Css属性display来显示或者隐藏
<body> <div id="app"> <h3>v-if 条件渲染</h3> <input v-model='seen' type="checkbox" name="" id="">勾选后显示 <div v-if='seen' :class='activeClass'></div> <p v-else>红块不显示了</p> <br> <h3>v-show 条件显示</h3> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm=new Vue({ el:'#app', data:{ activeClass:'box', seen:true } }); </script> </body>
4.7.2 v-if与v-show比较
**什么时候元素被渲染?
v-if如果在初始条件为假,则什么也不做,每当条件为真时,都会重新渲染条件元素
v-show不管初始条件是什么,元素总是会被渲染,并且基于CSS进行切换
**使用场景选择
v-if有更高的切换开销,
v-show有更高的初始渲染开销
因此,如果需要非常频繁地切换,则使用v-show比较好;如果在运行后条件很少改变,则使用v-if较好。
4.8 列表渲染 v-for
4.8.1 迭代数组
v-for="(alias,index) in array"
alias:数组元素迭代的别名;index:数组索引值从0开始(可选)
4.8.2 迭代对象的属性
v-for="(value,key,index) in Object"
value:每个对象的属性值;key:属性名(可选);index:索引值(可选)
4.8.3 可以of替代in作为分隔符
DEMO
<body> <div id="app"> <h3>v- for 遍历 列表渲染/迭代数组 </h3> <ul> <!-- e代表数组emp中的一个元素,index代表数组的下标/索引值 注意:使用key特殊属性,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素 注意:可以使用of或者in作为分隔符 --> <li v-for=' (e,index) in emp' :key="index"> {{index+1}}, {{e.name}},{{e.salary}} </li> </ul> <h3>迭代对象</h3> <ul> <!-- value key index 循环要注意顺序 value 对象的属性值 key 对象的属性名 index 索引值 --> <li v-for="(value,key,index) in person"> {{index}},{{key}},{{value}} </li> </ul> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { emp: [ { name: 'zq', salary: 2000 }, { name: 'q1', salary: 1800 }, { name: 'q2', salary: 1500 } ], person:{ name:'xxx0', sex:'man', old:17, salary:1500 } } }); </script> </body>
4.9 事件处理 v-on
4.9.1 事件处理方法
完整格式:v-on:事件名="函数名" 或 v-on:事件名="函数名(参数......)"
缩写格式:@事件名="函数名" 或 @事件名="函数名(参数......)" 注意:@后面没有冒号
event:函数中的默认形参,代表原生DOM事件
*当调用的函数,有多个参数传入时,需要使用原生DOM事件,则通过$event作为实参传入
作用:用于监听DOM事件
<body> <div id="app"> <h3>事件处理方法 v-on v-on:事件/@事件</h3> <button v-on:click="say">say {{ msg }}</button> <!-- $event 代表的是原生的Dom事件 --> <button @click="warm('zq',$event)">warm</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg:'hello' }, methods: { say: function (event) { alert(this.msg); alert(event.target.tagName); }, warm:function(value,$event){ alert(value+','+event.target.innerHTML); } } }); </script> </body>
4.9.2 事件修饰符
.stop 阻止单击事件继续传播 event.stopPropagation()
.prevent 阻止事件默认行为 event.preventDefault()
.once 点击事件将只会触发一次
<body> <div id="app"> <h3>事件修饰符</h3> <!-- 防止单击事件继续传播 --> <div @click="todo"> <button @click="dothis">单击事件会继续传播</button> </div> <br> <!-- .stop 阻止了单击事件的继续传播 --> <div @click="todo"> <button @click.stop="dothis">阻止单击事件继续传播</button> </div> <br> <!-- 阻止事件的默认行为 --> <a href="https://www.baidu.com" @click.prevent="dostop" target="_blank">baidu链接</a> <br> <br> <!-- 点击事件只会触发一次 --> <button @click.once="doOnly">只触发一次</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg:'hello' }, methods: { say: function (event) { alert(this.msg); alert(event.target.tagName); }, warm:function(value,$event){ alert(value+','+event.target.innerHTML); }, dothis: function () { alert("dothis..."); }, todo: function () { alert("todo"); }, dostop: function () { }, doOnly: function () { alert("doOnly"); } } }); </script> </body>
4.9.3 按键修饰符
格式:v-on:keyup.按键名 或 @keyup.按键名
常用按键名:.enter
.tab
.delete(捕获删除或退格键)
.esc
.space
.up
.down
.left
.right
<body> <div id="app"> <h3>按键修饰符或按键码</h3> <input type="text" @keyup.enter="KeyEnter"> <br> <input type="text" @keyup.space="KeySapce"> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg:'hello' }, methods: { say: function (event) { alert(this.msg); alert(event.target.tagName); }, warm:function(value,$event){ alert(value+','+event.target.innerHTML); }, dothis: function () { alert("dothis..."); }, todo: function () { alert("todo"); }, dostop: function () { }, doOnly: function () { alert("doOnly"); }, KeyEnter: function () { alert("当前按的是回车键!"); }, KeySapce:function(){ alert("当前按的是sapce键!"); } } }); </script> </body>
4.10 表单数据双向绑定v-model
v-model 指令用于表单数据双向绑定,针对以下类型:
text 文本
textarea 多行文本
radio 单选按钮
checkbox 复选框
select 下拉框
<body> <div id="demo"> <!-- @submit.prevent 阻止事件的默认行为,当前阻止的是action行为 --> <form action="#" @submit.prevent="addform"> 姓名(文本):<input type="text" v-model="userName"> <br><br> 性别(单选按钮): <input name="sex" type="radio" value="1" v-model='userSex' />男 <input name="sex" type="radio" value="0" v-model='userSex' />女 <br><br> 技能(多选框): <span v-for="(e,index) in checkSkills"> <input type="checkbox" name="skills" v-model='userSkill' v-bind:value="e.code"><span>{{e.skillName}}</span> </span> <!-- <input type="checkbox" name="skills" value="java" v-model="userSkill">Java开发 <input type="checkbox" name="skills" value="vue" v-model="userSkill">Vue.js开发 <input type="checkbox" name="skills" value="python" v-model="userSkill">Python开发 --> <br><br> 城市(下拉框): <select name="citys" v-model="chooseCity"> <option v-for=" (e,index) in userCity" v-bind:value="e.code"> {{ e.cityName }} </option> </select> <br><br> 说明(多行文本):<textarea cols="30" rows="5" v-model="desc"></textarea> <br><br> <button type="submit">提交</button> </form> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#demo', data: { userName: '', userSex: '1', userSkill: ['java', 'vue'], chooseCity: 'ks', userCity: [ { code: 'bj', cityName: '北京' }, { code: 'sh', cityName: '上海' }, { code: 'ks', cityName: '昆山' } ], checkSkills: [ { code: 'java', skillName: 'Java开发' }, { code: 'vue', skillName: 'Vue.js开发' }, { code: 'python', skillName: 'Python开发' } ], desc: '描述......' }, methods: { addform: function () { alert(this.userName + ', ' + this.userSex + ', ' + this.userSkill + ', ' + this.chooseCity + ', ' + this.desc) } } }); </script> </body>