vue---关于我和v-on、if、for、html...这些指令之间的那些事儿
本文是我在学习vue的过程中记录学习的点点滴滴,仅仅为了学完之后巩固一下,日后忘记了也可以方便快速的复习。
vue中常用的那些指令介绍
- 前言
- 一、什么是指令
- 二、指令系统
-
- 2.1、v-text、v-html
- 2.2、v-html
- 2.3、v-text、v-html、{{ }}的正确理解与区别
- 2.4、v-model
- 2.5、v-cloak
-
- 2.5.1、{{}}模板语法的不足
- 2.5.2、使用 v-cloak 来解决
- 2.6、v-bind
- 2.7、v-bind 绑定 class 和 style 属性
- 2.8、v-on指令及this、methods、push的含义
- 2.9、v-if
- 2.10、v-show
-
- 2.10.1、v-show
- 2.10.2、v-show VS v-if
- 2.11、v-for
-
- 2.11.1、循环数组
- 2.11.2、循环对象
- 2.11.3、循环对象数组(指数组元素值为对象)
- 2.11.4、遍历数字与字符串
- 2.12、v-once 与 v-pre
- 2.12、v-model 常用的三个修饰符
-
- 2.12.1、.lazy 修饰符
- 2.12.2、.number 修饰符
- 2.12.3、 .trim 修饰符
- 三、v-if 与 v-for 结合使用(循环与条件的结合)
前言
今天主要学习的是关于vue中那些常用的一些指令的介绍,包括v-text、v-html、v-model、v-cloak、v-bind、 v-on、v-if、v-show、v-for
一、什么是指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute【vue 指令都以 v-开头】。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for是例外情况)
二、指令系统
2.1、v-text、v-html
{{msg}}可以用 v-text 指令替代
以下两种效果一致,都是显示data中的msg的变量值,与{{ }}语法基一样但不完全相同:{{msg}}
v-text只会识别其中的字符串,并不会解析其中的标签
如果msg中的数据是一个链接:msg:'百度
<h1 v-text="msg"></h1>
显示结果:
2.2、v-html
v-html和v-text一样都是显示文本内容,也可以替代{{}},但是v-html会解析data中msg中的标签
例如我们来对v-text和v-html进行比较
<h1>{{msg}}</h1><h1 v-text="msg"></h1><h1 v-html="msg"></h1>
运行结果:
2.3、v-text、v-html、{{ }}的正确理解与区别
v-text 与 v-html 指令都可以更新页面元素的内容,不同的是,v-text 会将数据以字符串文本的形式更新,而 v-html 则是将数据以 html 标签的形式更新。当变量的值含有 html 标记时(如: 百度),v-html 会解析 html标记,v-text 就会原样显示。
在更新数据上,我们也可以使用 Mustache 语法(即{{}})进行更新数据,不同于 v-text、v-html 指令,{{}}表达式只会更新原本占位插值所在的数据内容,而 v-text、v-html 指令则会替换掉整个的内容
<body> <div id="app"> <p>+++++++++ {{msg}} -----------</p> <p v-text="msg">=================</p> <p v-text="msgHtml">==============</p> <p v-html="msgHtml">============</p> </div> <script> // model部分 var datamodel = { msg: "helloworld", msgHtml:"百度" } // viewmodel new Vue({ el: "#app",//element data:datamodel }) </script></body>
运行结果:
上面三种形式对于数据间的交互都是单向的,即只能将vue 实例里的值传递给页面,页面对数据值的任何操作却无法传递给model
2.4、v-model
在表单控件或者组件上创建双向绑定。
<div id="app">{{msg}}<input type="text" v-model="msg"></div><script>var vm= new Vue({el: '#app', data: {msg: 'hello world', }});</script>
此时改变输入框的值,data中msg的值也会跟着发生改变数据的双向绑定:{{msg}} :data.msg-->msg :input.msg-->data.msg
再次认识 MVVM 框架
MVVM 中最重要的一个特性,可以说就是数据的双向绑定,而vue 作为一个 MVVM 框架,理所应当的实现了数据的双向绑定,所以我们可以使用内置的 v-model 指令完成数据在 View 与Model 间的双向绑定。
当然,因为只有表单元素可以与用户进行交互,所以我们只能使用 v-model 指令在表单控件上创建双向绑定。对于组件的双向绑定,我们后续讲解。
2.5、v-cloak
2.5.1、{{}}模板语法的不足
上面{{}}模板语法还有一个不足:可能会出现闪烁问题,就是可能页面数据还没加载渲染完成,就提前看到了两对{}。
实际应用中可能就是 vue 实例中 data 数据,比如可能是通过发送异步请求获取数据,数据来自于网络(服务器),由于网络或者数据量大,需要一定的时间,这个时候 vue 中的 data 尚没有数据,就不会去渲染 view,那么在 view 中就会提前看到类似{{msg}},这就不太合适,所以需要在数据尚未渲染加载完成时不要让类似{{msg}}出现。
2.5.2、使用 v-cloak 来解决
可以使用 v-cloak 来解决。使用 v-cloak,需要配合 css 样式一起使用,否则不会生效。通过 css 样式先设置为不显示,在数据渲染完成之后就会自动修改 display
<style>[v-cloak] {display: none;}</style></head><body><div id="app"><h3 v-cloak> {{msg}}</h3></div><script>var vm = new Vue({el: '#app', data: {msg: '欢迎来到徐照兴课堂', },// 使用 created 函数作用就是测试页面尚未渲染数据时提前看到了{{}},created 是 vue 生命周期中的一个钩子函数,刚创建vue实例后立马执行钩子函数,页面尚未渲染数据created: function () {alert('vue 实例刚创建,页面尚未渲染数据')}});</script></body>
2.6、v-bind
v-bind 可以用来在标签上绑定标签的属性(例如:img 的 src、title 属性等等)和样式(可以用 style 的形式进行内联样式的绑定,也可以通过指定 class 的形式指定样式),同时,对于绑定的内容,是做为一个 js 变量,因此,我们可以对该内容进行编写合法的 js 表达式
语法: v-bind:属性="值"属性就是普通 html 属性,值就来自于 vue 中的数据v-bind 可以简写为:如:v-bind:src=" "简写为:src=" "
<img v-bind:src="url" :width="w" :height="h+'px'" :title="msg+'欢迎您'"
绑定的值也可以是表达式,如上述的h+'px'、msg+'欢迎您'
2.7、v-bind 绑定 class 和 style 属性
绑定 class 和 style 时语法相对比较复杂些。
1、绑定class:
:class=“fontmyvar” 双引号是到data里取数据
:class=“‘fontmy’” 要去style中取数据要再加一个单引号
:class=“[fontmyvar,bgmyvar]” 同时运用多个样式要用数组形式
:class=“{fontmy:flag,bgmy:false}” json 形式,键值对,键就是样式名,值固定为布尔型,即 true 或 false,true 表示应用该样式,false 表示不应用
this表示现在这个vue对象
<style>.fontmy{color:red;font-size:20px;}.bgmy{background-color: royalblue;}</style></head><body><div id="app"><p class="fontmy">徐照兴</p><!-- 徐照兴
--><p :class="'fontmy'">徐照兴 1</p><p :class="fontmyvar">徐照兴 2</p><p :class="[fontmyvar,bgmyvar]">徐照兴 3</p><p :class="{fontmy:flag,bgmy:false}">徐照兴 4</p><p :class="{fontmy:num>0,bgmy:false}">徐照兴 5</p><p :class="varStyle">徐照兴 6</p></div><script>var vm = new Vue({el: "#app", data: {fontmyvar:'fontmy', bgmyvar:'bgmy', flag:true, num:-3, varStyle:{fontmy:true,bgmy:true// 这个地方也可使用 flag 指定,但要在前面加上 this,即 this.flag}}})</script></body>
运行效果:
2、绑定style:
style里面的属性名要遵循驼峰命名法,属性值需要单引号引起来。
驼峰命名法:第一个单词以小写字母开始;从第二个单词开始以后的每个单词的首字母都采用大写字母。
vue中class使用font-size:20px,但在style中不允许使用-,直接使用驼峰命名法且属性值要用单引号:fontSize:‘20px’
<div id="app"><p :style="myStyle">徐照兴 1</p><p :style="[myStyle,myStyle2]">徐照兴 2</p></div><script>var vm = new Vue({el: "#app", data: {myStyle:{// 注意这里的属性名要使用驼峰命名法,属性值需要单引号引起来//驼峰命名法:第一个单词以小写字母开始;从第二个单词开始以后的每个单词的首字母都采用大写字母color:'blue', fontSize:'30px' },myStyle2:{backgroundColor:'#ccc' }}})</script>
运行结果:
2.8、v-on指令及this、methods、push的含义
用法:
v-on:事件名=”函数”。
事件名比如:click、dblclick、mousedown、mouseup 等等。
v-on:可以简写为@
<body> <div id="app"> <button @click="show()">点我</button> <button v-on:click="show()">点我</button> <hr> <button @mouseover="show">鼠标经过时执行</button> <button @dblclick="show">鼠标双击时执行</button> <hr> <button @click="add">向数组中添加一个元素</button> </div> <script> var vm = new Vue({ el: "#app", data: { arr:[12,23,34,45] }, methods: { show() { // alert("1111") console.log("这是一个show方法") }, add(){ console.log(this) console.log(this===vm) this.arr.push(88) vm.arr.push(99) console.log(this.arr) this.show(); } }, }) </script></body>
结果:
上述项目使用了v-on和@来绑定了事件,此外绑定的事件必须要在vue实例中的methods里面定义,并且事件也可以有参数。 可以看出上述使用===号来判断this是否全等于vm这个vue实例,控制台输出为true,
2.9、v-if
v-if 指令是根据表达式的真假值判断元素的显示与否。
v-if和v-else可以组合成三种组合(语法和逻辑与平时的if-else是一样的):
单分支:v-if
双分支:v-if v-else
多分支v-if v-elseif v-else
<body> <div id="app"><div v-if="flag">Yes</div><div v-else>no</div><div v-if="grade>90">优秀</div><div v-else-if="grade>70">中等</div><div v-else-if="grade>60">及格</div><div v-else>不及格</div> </div> <script> var vm = new Vue({ el: "#app", data: { flag:false, grade:78 }, methods: {}, }) </script></body>
结果:
特点:当 flag 值为 false 时 dom 元素会销毁,当为 true 时又会重新创建,如下 2 个图所示。
当需要同时隐藏多个div或其他标签时可以将多个div或其他标签放入template中通过改变template的v-if属性来同时显示或隐藏多个div或其他标签
2.10、v-show
2.10.1、v-show
v-show 指令也是根据表达式的真假值判断元素的显示与否,和v-if类似。
<body> <div id="app"><h1 v-show="flag">徐照兴欢迎您!</h1> </div> <script> var vm = new Vue({ el: "#app", data: { flag: false, }, methods: { }, }) </script></body>
特点:带有 v-show 的元素始终会被渲染并保留在 DOM 中。 v-show 只是简单地切换元素的 CSS 属性 display。
flag 为 true 时效果:
flag 为 false 时效果:
2.10.2、v-show VS v-if
用来根据表达式的值显示或隐藏元素,v-show 是通过display 实现,显示与隐藏只是切换 display 属性;v-if 每次删除后重新创建,即显示与隐藏是在销毁与创建元素之间切换。
<div id="app"><div style="width:100px;height:100px;background-color:red;" v-show="flag">欢迎来到徐照兴课堂</div><hr><!-- --><button v-on:click="change">隐藏/显示</button><button v-on:click="flag=false">隐藏</button><button v-on:click="flag=!flag">隐藏/显示</button></div><script>var vm = new Vue({el: "#app", data: {//存储数据地方flag:true},methods:{change(){// this.flag=false;//隐藏this.flag=!this.flag;//隐藏与显示切换}}})</script>
结果:
使用this.flag=!this.flag;取反,可以反复单击该按钮改变flag的值并显示或隐藏上述div,为true时改为false,为false时改为true
分析:上面是通过 v-show 显示与隐藏,切换到代码查看器,会发现 div 的显示与隐藏是通过 display 是否为 none。
如果把 v-show 换成 v-if,则当 v-if 后面表达式值为 false 时,是销毁整个 div 元素,为 true 时,则重新创建。
1、v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。2、v-show 不支持 元素,也不支持 v-else。一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,当我们需要频繁控制元素的显示与否时,推荐使用v-show 指令,避免因为使用 v-if 指令而造成的高性能消耗。
2.11、v-for
v-for 指令,可以对数组、对象、数字、字符串进行循环,获取到源数据的每一个值。使用 v-for 指令,必须使用特定语法 item in items ,其中 items 是源数据(数组、字符串等),而 item 则是当前遍历的元素的别名,这里类似于 C# 中的 foreach 的循环格式。
2.11.1、循环数组
<div id="app"><ul><li v-for="value in arr">{{ value }}</li></ul></div><script>var app4 = new Vue({el: '#app', data: {arr: [1,2,3,4,5]}})</script>
运行结果:
2.11.2、循环对象
<div id="app"><ul><li v-for="value in user">{{value}}</li></ul><ul><li v-for="(value,key,index) in user">{{index}}:{{key}}={{value}}</li></ul><ul></div><script>var app4 = new Vue({el: '#app', data: {arr: [1,2,3,4,5], user:{id:1,username:'张三',age:20,sex:'男'}, }})</script>
运行结果:
2.11.3、循环对象数组(指数组元素值为对象)
<div id="app"><ul><li v-for="(user,index) in users">{{index+1}}- {{user.id}}-{{user.username}}-{{user.sex}}</li></ul></div><script>var vm = new Vue({el: '#app', data: {users:[{id:1,username:'张三',age:20,sex:'男'}, {id:2,username:'李四',age:22,sex:'女'}, {id:3,username:'王五',age:23,sex:'男'}, ]}})</script>
运行结果:
2.11.4、遍历数字与字符串
<span v-for="item in 5" :key="item">{{ item }}</span><hr><span v-for="item in '徐照兴'" :key="item">{{ item }}</span
结果:
使用 v-for 时尽量提供 key,提高修改元素的效率
通过指定:key 属性为每个元素绑定一个唯一的 key(index唯一也可以),其优势是当更新元素时可重用元素提高效率。
也就是说假设数组 arr2 元素值发生变化时,如果没有:key
属性,那么会把 arr2 所有值先删除再重新插入。有 key 的话就会重用原有元素,也就是在原先基础上修改
<div id="app"><ul><li v-for="value in arr2">{{value}}</li><hr><li v-for="(value,key) in arr2" :key="key">{{value}}</li></ul></div><script>var app4 = new Vue({el: '#app', data: {arr2: [1,2,3,4,5], }})</script>
2.12、v-once 与 v-pre
v-once 只绑定一次。
v-pre 不解析{{}}
<body> <div id="app"> <input type="text" v-model="msg">{{msg}}</input> <h3 v-once>{{msg}}</h3> <h3 v-pre>{{msg}}</h3> <!-- {{hello vue}}
这里如果没有 v-pre 指令就会报错, 因为会认为 hello vue 是 data 里的一个属性,而实际不存在,所以会报错--> <h3 v-pre>{{hello vue}}</h3> </div> <script> var vm = new Vue({ el: "#app", data: { msg:"欢迎来到小豆子学堂" }, }) </script></body>
结果:
此外,v-pre指令会导致跳过这个元素和它的子元素的编译过程。加快编译。
例如:网页中的一篇文章,文章内容不需要被 Vue 管理渲染,则可以在此元素上添加 v-pre 指令,将会忽略对文章编译(也就是不去检测文章内容是否含有 vue 的语法,并对其进行解析),从而提高性能。
2.12、v-model 常用的三个修饰符
2.12.1、.lazy 修饰符
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。也就是文本框中输入的与显示的同步,每输入一个字符都会同步显示。而可以添加.lazy 修饰符,从而转变为失去焦点同步。也就是说现在在文本框中输入字符是,msg 的值不会及时改变,要等光标移到文本框外面才同步改变。
<body> <div id="app"><input type="text" v-model.lazy="msg">{{msg}}</input> </div> <script> var vm = new Vue({ el: "#app", data: { msg:"hello" }, }) </script></body>
结果:
2.12.2、.number 修饰符
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符
<body> <div id="app"><input type="text" v-model.lazy="msg">{{msg}}</input> <input type="text" v-model.lazy="num1">{{num1}}</input> <input type="text" v-model.lazy="num2">{{num2}}</input> <br> {{num1+num2}} </div> <script> var vm = new Vue({ el: "#app", data: { msg:"hello", num1:1, num2:2 }, }) </script></body>
v-model 后面加了.number,即是转为数值型数据,就只能是求和。
也可以用不加.number使用 parseInt 进行转换,即上面的注释{{parseFloat(num1)+parseFloat(num2)}},效果一样是求和。
2.12.3、 .trim 修饰符
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符
<body> <div id="app"><input type="text" v-model.trim="msg">{{msg}}</input> </div> <script> var vm = new Vue({ el: "#app", data: { msg:"hello", }, }) </script></body>
结果:
有了 trim 修饰,只要光标离开了文本框在其他地方单击 下,两端若有空格就会自动去掉
三、v-if 与 v-for 结合使用(循环与条件的结合)
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,
当你只想为部分项渲染节点时,这种优先级的机制会十分有用。也就是说当 v-if 与 v-for 一起使用时,v-for 循环在外,v-if 条件判断在内部。
<body> <div id="app"><ul> <li v-for="item in items" v-if="item.isOK">{{item.text}}</li></ul> </div> <script> var vm = new Vue({ el: "#app", data: { arr:[1,2,3,4,5], items:[ {text:'vue',isOK:true}, {text:'react',isOK:true}, {text:'angular',isOK:true}, {text:'html5',isOK:false}, {text:'css3',isOK:false} ] }, }) </script></body>
结果:
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素上。
<body> <div id="app"><ul v-if="isOK"> <li v-for="item in items">{{item.text}}</li></ul> </div> <script> var vm = new Vue({ el: "#app", data: { isOK:true, items:[ {text:'vue',isOK:true}, {text:'react',isOK:true}, {text:'angular',isOK:true}, {text:'html5',isOK:false}, {text:'css3',isOK:false} ] }, }) </script></body>
运行结果:
如果我把上面 isOK 后面的 true 改为 false,就不会显示整个无序列表内容。