vue--常用指令和事件修饰符
安装
下载:https://cn.vuejs.org/v2/guide/installation.html
直接通过script在head标签里导入就可以了
<script src="../static/vue.min.js"></script>
或者通过CDN的方式直接引用
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
模版语法
大家都知道django里的模版语法是{{ }},事情总是巧合的,Vue里的模版语法也是{{ }}
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <!-- 模版语法--> <h1>{{ msg }}</h1> </div> <script> // 实例化对象 new Vue({ el:"#app", // 固定写法el,查找的元素 data:{ // 固定写法,是个object,里面放的数据 msg:"hello vue" // 数据,前面的为模版里放的变量名,后面为对应的数据 } }) </script> </body> </html>
上面使用的是vue的方法查找id为app的属性,并将里面的文本替换为“hello vue”
指令
指令就是帮我们渲染数据的,语法:v-指令
上面的代码我们可以用指令v-text来实现
v-text
v-text相当于innerText,v-html相当于innerHTML,其实和上面的模版语法效果一样
data中是一个函数,函数中return一个对象,可以是空对象,但不能return
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <!-- 模版语法--> <h1 v-text="msg"></h1> <!-- 写在标签里面--> </div> <script> // 实例化对象 new Vue({ el:"#app", // 固定写法el,查找的元素 data(){ return { msg:"<h2>hello vue</h2>" } } }) </script> </body> </html>
上面的将msg的内容原样显示在了页面上,没有当成标签渲染后显示,如果要渲染后显示在页面上,
就要用到v-html了
v-html
v-text相当于innerText,v-html相当于innerHTML
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <!-- 模版语法--> <h1 v-html="msg"></h1> <!-- 写在标签里面--> </div> <script> // 实例化对象 new Vue({ el:"#app", // 固定写法el,查找的元素 data(){ <!--data中是一个函数,函数中return一个对象,可以是空对象,但不能return--> return { msg:"<h2>hello vue</h2>" } } }) </script> </body> </html>
v-for
v-for可以迭代数组和迭代对象
v-for迭代数组
- 语法:v-for="(alias,index) in array"
- 说明:alias是数组迭代的别名,index数组索引值,从0开始(可选,如果有就要加小括号)
v-for迭代对象的属性
- 语法: v-for=“(value,key,index) in object”
- 说明:value每个对象的属性值,key为属性名(可选),index为索引(可选)
<!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>1.迭代数组</h3> <ul> <!-- e 代表的是emps数组的别名,index 数组下标,从0开始 的 注意:使用 key 特殊属性, 它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素 可以使用of或者in作为分隔符 --> <li v-for="(e, index) of emps" :key="index"> 编号:{{index+1}},姓名: {{e.name}} , 工资 :{{e.salary}} </li> </ul> <h3>2.迭代对象</h3> <ul> <!-- value对应是的对象的属性值,key就是对象的属性名,index索引值 --> <li v-for="(value, key, index) in person"> 第{{index+1}}个属性为:{{key}} = {{value}} </li> </ul> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { emps: [ {name: '马云', salary: '20000'}, {name: '马化腾', salary: '18000'}, {name: '东哥', salary: '13000'} ], person: { name: '小梦', age: 18 } } }) </script> </body> </html>
结果:
列表
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <ul> <li v-for="student in students">{{student}}</li> </ul> </div> <script> new Vue({ el:"#app", data:{ students: ["张三","李四","王五"] } }) </script> </body> </html>
字典
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <ul> <li v-for="student in students">姓名:{{student.name}},年龄:{{student.age}},职业:{{student.job}}</li> </ul> </div> <script> new Vue({ el:"#app", data:{ students: [ { name:"张三", age: 25, job:"test" }, { name:"李四", age: 56, job:"IT" }, { name:"王五", age: 85, job:"dev" } ] }}) </script> </body> </html>
v-if
v-if是否渲染当前元素,v-show 与v-if类似,只是元素始终会被渲染并保留在DOM中,只是简单切换元素的CSS属性display来显示或隐藏
案例
<!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> <script src="./node_modules/vue/dist/vue.js"></script> <style> .box{ height: 200px; width: 200px; background: red; } </style> </head> <body> <div id="app"> <input v-model="seen" type="checkbox" name="" id="">勾选后显示红色小块 <div v-if="seen" class="box"> </div> <p v-else>红色小块隐藏了</p> </div> <script> new Vue({ el: "#app", data: { seen: false, } }) </script> </body> </html>
v-show
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> <style> .box { width: 200px; height: 200px; background-color: red; } .box2 { width: 200px; height: 200px; background-color: green; } </style> </head> <body> <div id="content"> <button v-on:click='handlerClick'>隐藏</button> <div class="box" v-show='isShow'></div> </div> <script> //数据驱动视图 new Vue({ el: '#content', data() { //data中是一个函数 函数中return一个对象,可以是空对象 但不能不return return { msg: "<h2>alex</h2>", num: 1, isShow: true } }, methods: { handlerClick() { //数据驱动 console.log(this); this.isShow = !this.isShow; //取反 } } }) </script> </body> </html>
当第一次点击隐藏按钮的时候,isShow变为false,隐藏红色的框(加了个样式,display: none;)。当第二次点击的时候,因为isShow为fasle,所以取反之后变为true,显示红色的框
v-show要使用methods里的函数
当isshow为false的时候,页面的html是通过display:none,把内容隐藏了
切换性能:
v-show的切换性能高一些,display: none, v-if的切换是通过append
加载性能:
v-show的慢,v-if的快
v-on
点击事件,要写在methods里面
事件处理方法
- 完整格式:v-on:事件名=“函数名” 或 v-on:事件名="函数名(参数...)"
- 缩写格式:@事件名="函数名" 或 @事件名="函数名(参数)" 注意@后面没有:
- event:函数中的默认形参,代表原生DOM事件,当调用的函数有多个参数传入时,需要使用原生DOM事件,则通过$event作为实参传入,用于监听DOM事件
<!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>1. 事件处理方法 v-on 或 @</h3> <button v-on:click="say">Say {{msg}}</button> <!-- $event代表的是原生 的Dom事件 --> <button @click="warn('hello', $event)">Warn</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'Hello World!!', num: 0 }, methods: { //定义事件处理函数 say: function (event) { // event代表的是Dom原生事件, Vue.js它会自动 的将它传入进来, alert(this.msg) alert(event.target.innerHTML) }, warn: function (name, event) { //如果说函数有多个参数,而双需要使用原生事件,则需要使用 $event 作为 参数传入 alert(name + ',' + event.target.tagName) } } }) </script> </body> </html>
事件修饰符
- .stop阻止单击事件继续传播
- .prevent阻止事件默认行为
- .once点击事件只会触发一次
<!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>2. 事件修饰符</h3> <!-- 2.1 防止单击事件继续传播 --> <div @click="todo"> <!-- 点击doThis之后还会触发todo事件 --> <button @click="doThis">单击事件会继续传播</button> </div> <br> <div @click="todo"> <!-- .stop作用:是阻止事件的传播,点击doThis之后不会触发todo事件 --> <button @click.stop="doThis">阻止单击事件会继续传播</button> </div> <br> <!-- 2.2 阻止事件的默认行为,不加prevent会跳转到百度 --> <a href="http://www.baidu.com" @click.prevent="doStop">百度</a> <!-- 2.3 点击事件只会触发一次 --> <button @click.once="doOnly">点击事件只会触发一次:{{num}}</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { num: 0 }, methods: { //定义事件处理函数 doThis: function () { alert('doThis....') }, todo: function () { alert('todo....') }, doStop: function () { alert('doStop...href默认行为已经被阻止') }, doOnly: function () { this.num ++ } }, }) </script> </body> </html>
按键修饰符
- 格式: v-on:keyup.按键名 或 @keyup.按键名
- 常用按键名
- .enter .tab .delete .esc .space .up .down
<!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> <!-- 回车键可以用做提交表单数据,比如搜索框 --> <input type="text" @keyup.enter="keyEnter"> <input type="text" @keyup.space="keySpace"> <input type="text" @keyup.13="keyCode"> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', methods: { //定义事件处理函数 keyEnter: function () { alert('当前按的是回车键') }, keySpace: function() { alert('当前按的是空格键') }, keyCode: function () { alert('按的是13') } }, }) </script> </body> </html>
例子二
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <script src="../static/vue.min.js"></script> <style> .active{ color: red; } </style> </head> <body> <div id="app"> <h1 :class="{active: isActive}">钢铁侠</h1> <!-- 添加class属性为active --> <button v-on:click="ChangeColor">点我让钢铁侠变红</button> </div> <script> new Vue({ el:"#app", data:{ isActive: false }, methods:{ ChangeColor:function () { this.isActive = !this.isActive; // 取反 }, } } ) </script> </body> </html>
v-bind
通过class列表和style指定样式是数据绑定的一个常见需求,他们都是元素的属性,都用v-bind处理,其中表达式结果的类型可以是:字符串,对象或数组
语法格式
- v-bind:class="表达式" 或 :class="表达式"
class的表达式可以为:
- 字符串 :class="activeClass"
- 对象 :class="{active:isActive,error:hasError}"
- 数组 :class="['active','error']" 注意要加上单引号,不然获取的是data中的值
style的表达式一般为对象
- :style="{color:activeColor,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> <script src="./node_modules/vue/dist/vue.js"></script> <style> .active{ color:green; } .delete{ background: red; } .error{ font-size: 35px; } </style> </head> <body> <div id="app"> <h3>Class绑定,v-bind:class 或者 :class</h3> <!-- <p class="active">字符串表达式</p> --> <p v-bind:class="activeClass">字符串表达式</p> <!-- key值是样式名,value是data中绑定的属性 --> <!-- 当isDelete为true的时候,delete就会进行渲染 --> <p :class={delete:isDelete,error:hasError}> 对象表达式</p> <p :class="['active','error']">数组表达式</p> <h3>Style绑定,v-bind:style 或 :style</h3> <p :style="{color: activeColor, fontSize: fontSize + 'px'}">Style绑定</p> </div> <script> new Vue({ el: "#app", data: { activeClass: 'active', isDelete: false, hasError: true, activeColor: 'red', fontSize: 100 } }) </script> </body> </html>
例子二:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> <style> .box { width: 200px; height: 200px; background-color: red; } .active{ background-color: green; } </style> </head> <body> <div id="app"> <button v-on:click = 'handlerChange'>切换颜色</button> <!--v-bind 标签中所有的属性 img标签src alt,a标签的href title id class--> <img v-bind:src="imgSrc" v-bind:alt="msg"> <div class="box" v-bind:class = '{active:isActive}'></div> </div> <script> new Vue({ el: '#app', data() { return { imgSrc:'./1.jpg', msg:'美女', isActive:true } }, methods:{ handlerChange(){ this.isActive = !this.isActive; }, } }) </script> </body> </html>
<div class="box" v-bind:class = '{active:isActive}'></div>
div原来有一个class属性,值只有一个box,通过v-bind绑定了一个属性active,isActive为true时把active添加到class里,为false时不添加
<button v-on:click = 'handlerChange'>切换颜色</button>
绑定了一个v-on的click事件,当第一次点击按钮时,去methods里找handlerChange,因为刚开始isActive为true(data里),点击后取反为false,
这时data里的也为false,所以没有active属性
v-on和v-bind的简写
v-bind可以简写为 : v-on可以简写为@
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> <style> .box { width: 200px; height: 200px; background-color: red; } .active{ background-color: green; } </style> </head> <body> <div id="app"> <button @mouseenter = 'handlerChange' @mouseleave = 'handlerLeave'>切换颜色</button> <!--v-bind 标签中所有的属性 img标签src alt,a标签的href title id class--> <img :src="imgSrc" :alt="msg"> <div class="box" :class = '{active:isActive}'></div> </div> <script> // v-bind和v-on的简便写法 : @ new Vue({ el: '#app', data() { return { imgSrc:'./1.jpg', msg:'美女', isActive:true } }, methods:{ handlerChange(){ this.isActive = false; }, handlerLeave(){ this.isActive = true; } } }) </script> </body> </html>
v-model
双向绑定,当用户输入的时候,改变原来的值,只能应用在像input,textare,select之类的标签
v-model也叫双向数据绑定
例子一:
<!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> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="demo"> <!-- @submit.prevent 阻止事件的默认行为,当前阻止的是action行为 --> <form action="#" @submit.prevent="submitForm"> 姓名(文本):<input type="text" v-model="name"> <br><br> 性别(单选按钮): <input name="sex" type="radio" value="1" v-model="sex"/>男 <input name="sex" type="radio" value="0" v-model="sex"/>女 <br><br> 技能(多选框): <input type="checkbox" name="skills" value="java" v-model="skills">Java开发 <input type="checkbox" name="skills" value="vue" v-model="skills">Vue.js开发 <input type="checkbox" name="skills" value="python" v-model="skills">Python开发 <br><br> 城市(下拉框): <!-- 绑定在select上才会默认选中 --> <select name="citys" v-model="city"> <option v-for="c in citys" :value="c.code"> {{c.name}} </option> </select> <br><br> 说明(多行文本):<textarea cols="30" rows="5" v-model="desc"></textarea> <br><br> <button type="submit" >提交</button> </form> </div> <script> new Vue({ el: '#demo', data: { name: '', sex: '1', //默认选中的是 男 skills: ['vue', 'python'], //默认选中 Vue.js开发 、Python开发 citys: [ {code: 'bj', name: '北京'}, {code: 'sh', name: '上海'}, {code: 'gz', name: '广州'} ], city: 'sh', // 默认选中的城市:上海 desc: '' }, methods: { submitForm: function () { //处理提交表单 //发送ajax异步处理 alert(this.name + ', ' + this.sex + ', ' + this.skills + ', ' + this.city + ', ' + this.desc) } } }) </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>Document</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- {{}}用于标签体内显示数据 --> hello,{{ msg }} <br> <!-- v-model进行数据的双向绑定 --> <input type="text" v-model="msg"> </div> <script > new Vue({ el: "#app", //指定被Vue管理的入口, 值为选择器, 不可以指定body或者是html data: { // 用于初始化数据,在Vue实例管理的Dom节点下,可通过模板语法来引用 msg: "vue.js" } }) </script> </body> </html>
会把msg的信息显示在输入框和div标签里,更改输入框里的数据,div里的也会跟着改,所以叫双向数据绑定
计算属性
computed 选项定义计算属性
计算属性 类似于 methods 选项中定义的函数
- 计算属性 会进行缓存,只在相关响应式依赖发生改变时它们才会重新求值。
- 函数 每次都会执行函数体进行计算。
输入数学与英语分数,采用 methods 与 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>Document</title> </head> <body> <div id="app"> 数学:<input type="text" v-model="mathScore"> 英语:<input type="text" v-model="englishScore"><br> <!-- v-model调用函数时,不要少了小括号 --> 总得分(函数-单向绑定):<input type="text" v-model="sumScore()"><br> <!-- 绑定计算属性后面不加上小括号 --> 总得分(计算属性-单向绑定):<input type="text" v-model="sumScore1"><br> 总得分(计算属性-双向绑定):<input type="text" v-model="sumScore2"> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> /* 1. 函数没有缓存,每次都会被调用 2. 计算属性有缓存 ,只有当计算属性体内的属性值被更改之后才会被调用,不然不会被调用 3. 函数只支持单向 4. 计算属性默认情况下:只有getter函数,而没有setter函数,所以只支持单向 如果你要进行双向,则需要自定义setter函数 */ var vm = new Vue({ el: '#app', data: { mathScore: 80, englishScore: 90, }, methods: { sumScore: function () { //100 console.log('sumScore函数被调用') // this 指向的就是 vm 实例 , 减0是为了字符串转为数字运算 return (this.mathScore-0) + (this.englishScore-0) } }, computed: { //定义计算属性选项 //这个是单向绑定,默认只有getter方法 sumScore1: function () { //计算属性有缓存,如果计算属性体内的属性值没有发生改变,则不会重新计算,只有发生改变 的时候才会重新计算 console.log('sumScore1计算属性被调用') return (this.mathScore-0) + (this.englishScore-0) }, sumScore2: { //有了setter和getter之后就可以进行双向绑定 //获取数据 get: function() { console.log('sumScore2.get被调用') return (this.mathScore-0) + (this.englishScore-0) }, //设置数据, 当 sumScore2 计算属性更新之后 ,则会调用set方法 set: function(newValue) { // newVulue 是 sumScore2 更新之后的新值 console.log('sumScore2.set被调用') var avgScore = newValue / 2 this.mathScore = avgScore this.englishScore = avgScore } } }, }) </script> </body> </html>
computed 选项内的计算属性默认是 getter 函数,所以上面只支持单向绑定,当修改数学和英语的数据才会更新总分,而修改总分不会更新数据和英语
如果是用户输入的,那会直接拼接起来,因为用户输入的数字也会被当成字符串。可以使用number来解决这个问题
<td><input type="text" v-model.number="python" /></td> <td><input type="text" v-model.number="vue"></td> <td><input type="text" v-model.number="selenium"></td>
上面当我们输入时,vue会监听我们输入的内容,这样大大降低了性能,我们可以使用lazy,当失去光标的时候再执行
<td><input type="text" v-model.number.lazy="python" /></td> <td><input type="text" v-model.number.lazy="vue"></td> <td><input type="text" v-model.number.lazy="selenium"></td>
实战
图片切换(图片放自己的路径)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <title>Title</title> <!-- 引用vue--> <script src="../static/vue.min.js"></script> </head> <body> <div id="app"> <img :src="images[currenIndex].imageSrc" alt=""><!-- 按索引取图片--> <br> <button @click="preImage">上一张</button> <!-- 绑定点击事件--> <button @click="nextImage">下一张</button> </div> <script> new Vue({ el:"#app", data(){ return{ images:[ {id:1,imageSrc:"../image/1.jpg"}, {id:2,imageSrc:"../image/2.jpg"}, {id:3,imageSrc:"../image/3.jpg"}, ], currenIndex:0 } }, methods:{ <!-- 点击下一张按钮时调用这个方法--> nextImage(){ this.currenIndex++; if (this.currenIndex == 3){ this.currenIndex=0; } }, preImage(){ if (this.currenIndex == 0) { this.currenIndex=3; } this.currenIndex--; } }, created(){ //组件,ajax setInterval(()=>{ this.currenIndex++; if (this.currenIndex == 3){ this.currenIndex=0; } },2000) } }) </script> </body> </html>