插值表达式

数据绑定最常见的形式就是使用”Mustache”语法(双大括号)的文本插值。vue提供了完全的javascript表达式支持。

  1. <!-- 可以进行运算 -->
  2. {{ 2 + 1}}
  3. <!-- 可以进行逻辑判断 -->
  4. {{ ok ? 'YES' : 'NO'}}
  5. <!-- 其他js表达式 -->
  6. {{ Date.now() }}

插值表达式的限制是:每个绑定只能包含单个表达式,所以下面的语句不会生效:

  1. <!-- 这是语句,不是表达式 -->
  2. {{ var a = 1}}
  3. <!-- 流控制不会生效,需要换成三目运算形式 -->
  4. {{ if(ok) { return message } }}

常用系统指令

v-on

可以使用v-on指令监听DOM事件,并在触发时运行一些JavaScript代码。

例如:使用v-on:click处理onclick事件

  1. 在vue接管的div中添加一个button标签,标签使用v-on:click="fun1('hello vue v-on')",为该button绑定一个点击事件,触发方法fun1,方法传值hello vue v-on
  2. 在vue的js代码中,添加methods属性,并在该属性内添加触发的方法定义
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>v-on:click</title>
  6. <script src="js/vuejs-2.5.16.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. {{message}}
  11. <!-- 绑定的事件函数如果直接写成fun1,不加参数,则会默认传入一个event事件 -->
  12. <!-- 但是如果使用 fun1('aaa') 传入了一个参数,那么event就没有了 -->
  13. <!-- 如果还想传入event参数,可以写成 fun1('aaa', $event) -->
  14. <button v-on:click="fun1('hello vue v-on')">vue的onclick</button>
  15. </div>
  16. </body>
  17. <script>
  18. //view model
  19. new Vue({
  20. el: "#app",
  21. data: {
  22. message: "hello vue"
  23. },
  24. methods: {
  25. fun1:function (msg) {
  26. // 或者简写为
  27. // fun1(msg) {
  28. alert("hello");
  29. this.message = msg;
  30. }
  31. }
  32. })
  33. </script>
  34. </html>

使用v-on:keydown绑定按键按下事件,使用$event作为参数获取事件对象:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>v-on:keydown</title>
  6. <script src="js/vuejs-2.5.16.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <!-- 绑定的方法只写了方法名,不写参数时,会默认传入一个event事件参数 -->
  11. <!-- <input type="text" v-on:keydown="fun"> -->
  12. <!-- 向vue方法传递event对象时,也可以使用$event进行传值 -->
  13. <input type="text" v-on:keydown="fun($event)">
  14. </div>
  15. </body>
  16. <script>
  17. new Vue({
  18. el: "#app",
  19. methods: {
  20. // vue 中的event对象,和传统js中的event对象是一样的
  21. fun:function(event) {
  22. if(event.keyCode == 13) {
  23. alert(1);
  24. }
  25. }
  26. }
  27. })
  28. </script>
  29. </html>

v-on可以简写为@,例如:

  1. <input type="text" v-on:keydown="fun($event)">
  2. <!-- 简写 -->
  3. <input type="text" @keydown="fun($event)">

vue中为v-on提供了事件修饰符来处理dom事件细节,如event.preventDefault()event.stopPropagation()

vue中阻止事件传播:

<div id='parent'>内部有一个<div id='child'>,此时如果鼠标移动到child上时,会先触发child绑定的鼠标移入事件;执行完child鼠标移入事件绑定的function后,会继续向上传播给parent,再触发parent上绑定的鼠标移入事件。

在传统js中,如果在执行了child的鼠标移入事件后,不想继续传播给parent,可以通过调用event对象的stopPropagation()终止事件的传播。

例如:

  1. function childMouseOver() {
  2. alert('鼠标移动到child上了');
  3. event.stopPropagation(); // 终止事件的传播
  4. }
  5. function parentMouseOver() {
  6. alert('鼠标移动到parent上了');
  7. }

因为vue的event对象和传统js的event对象是相同的,所以在vue中,如果要阻止事件的传播,也可以使用该语句:

  1. event.stopPropagation();

事件修饰符

vue通过由点(.)标示顿指令后缀来调用修饰符:

  • .stop:阻止事件冒泡(向上层传播)。同js的event.stopPropagation()
  • .prevent:阻止事件的默认行为,例如<a>标签的跳转等。同js的event.preventDefault()
  • .capture:使用事件的捕获模式
  • .self:只有event.target是当前操作的元素时才触发事件
  • .once:事件只触发一次
  • .passive:事件的默认行为立即执行,无需等待事件回调执行完毕。例如:在有滚动条的页面使用@wheel监控鼠标的滚轮滚动事件,不加.passive时,需要等该事件绑定的函数执行完毕后,滚动条才会向下滚动;加上.passive后,即使滚轮绑定的函数没有执行完,滚动条也会立即开始滚动。

表单提交前验证(表单提交前,验证方法如果不通过,则不进行提交):

传统的js:

  1. 绑定一个方法到onsubmit事件,onsubmit需要使用return xxxxx(),否则即使验证不通过也依然会提交
  2. 绑定的方法需要有一个明确的boolean类型返回值,验证通过返回true,验证不通过返回false
  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <div id="app">
  5. <!-- 此处的onsubmit需要使用 return checkForm()。 -->
  6. <form action="https://www.baidu.com" method="post" onsubmit="return checkForm()">
  7. <input type="submit" value="提交">
  8. </form>
  9. </div>
  10. </body>
  11. <script>
  12. function checkForm() {
  13. alert(1);
  14. // 表单验证必须有一个明确的boolean类型返回值
  15. return false;
  16. }
  17. </script>
  18. </html>

vue使用.prevent方式阻止表单提交:

  1. <div id="app">
  2. <!-- 使用.prevent阻止表单提交 -->
  3. <form @submit.prevent action="https://www.baidu.com" method="post">
  4. <input type="submit" value="提交">
  5. </form>
  6. </div>
  7. <script>
  8. // 需要vue接管该区域
  9. new Vue({
  10. el: '#app'
  11. });
  12. </script>

vue调用.stop修饰符的方式阻止事件冒泡传播:child在parent里面,鼠标移入child时除了触发child的鼠标移入事件,也会冒泡给parent。但是加上.stop后,在执行完child的方法后,不再向上冒泡执行parent的方法。

  1. <div id='child' @mouseover.stop="fun2($event)"></div>

vue使用.capture使用事件的捕获模式:

未使用.capture时:事件捕获阶段:点击事件会先捕获到外面的div1,后捕获到里面的div2。事件冒泡阶段:先执行里面的div2的事件方法,再冒泡执行div1的事件方法。

  1. <body>
  2. <div id="app">
  3. <div id="div1" @click="showMsg(1)">
  4. div1
  5. <div id="div2" @click="showMsg(2)">
  6. div2
  7. </div>
  8. </div>
  9. </div>
  10. </body>
  11. <script>
  12. Vue.config.productionTip = false;
  13. const vm = new Vue({
  14. el: '#app',
  15. methods: {
  16. showMsg(msg) {
  17. console.log(msg);
  18. }
  19. }
  20. });
  21. </script>

在div1加上.capture,启用捕获模式:

因为在捕获阶段是先捕获的外面的div1,所以加上.capture后,会先执行外面div1的绑定事件方法,后执行里面的div2事件方法

  1. <body>
  2. <div id="app">
  3. <div id="div1" @click.capture="showMsg(1)">
  4. div1
  5. <div id="div2" @click="showMsg(2)">
  6. div2
  7. </div>
  8. </div>
  9. </div>
  10. </body>
  11. <script>
  12. Vue.config.productionTip = false;
  13. const vm = new Vue({
  14. el: '#app',
  15. methods: {
  16. showMsg(msg) {
  17. console.log(msg);
  18. }
  19. }
  20. });
  21. </script>

事件修饰符可以流式处理,连续使用多个:

例如:先阻止冒泡,再阻止弹窗

  1. <a href="https://www.baidu.com" @click.stop.prevent="showInfo">点击提示信息</a>

按键修饰符

vue允许为v-on在监听键盘事件时添加按键修饰符:

按键修饰符别名:

  • .enter
  • .tab
  • .delete(捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
  • .ctrl
  • .alt
  • .shift
  • .meta(Windows按键)

vue调用.enter获取回车键、调用delete获取删除键:

  1. <body>
  2. <div id="app">
  3. test:<input type="text" @keydown.enter="fun1" @keydown.delete="fun2">
  4. <br>
  5. <!-- alt+C 组合键 -->
  6. test2:<input type="text" @keydown.alt.67="fun3">
  7. </div>
  8. </body>
  9. <script>
  10. new Vue({
  11. el: '#app',
  12. methods: {
  13. fun1: function () {
  14. alert("按下了回车键");
  15. },
  16. fun2: function () {
  17. alert("按下了删除键");
  18. },
  19. fun3: function () {
  20. alert("同时按下了alt和C");
  21. }
  22. }
  23. });
  24. </script>

也可以使用按键的键名,例如:

  1. @keydown.Enter // 此处的Enter是按键键名,vue中的enter是vue为该按键起的别名
  2. // 获取键名和键值的方式:
  3. let keyName = event.key;
  4. let keyCode = event.keyCode;
  5. // 该方式对单个单词的键名有效,例如Enter、Control
  6. // 对于多个单词组成的键名,需要将单词转成小写,单词间使用横线连接
  7. @keydown.CapsLock // 该写法无效,因为CpasLock是两个单词
  8. @keydown.caps-lock // 该写法可以正常识别

或者使用键值进行修饰(不推荐):

虽然部分浏览器还支持这种写法,但是将来可能会被移除。不推荐使用这种写法。不同用户的键盘键值可能也有差异。

  1. @keydown.13 // 按下回车键

也可以自定义按键别名:(也不推荐)

  1. Vue.config.keyCodes.自定义键名 = 键码

对于tab键,不适合使用keyup事件,因为tab键本身就会切换焦点,按下tab键后焦点就移动到其他地方去了。所以对于tab键,一般使用keydown事件。

ctrl、alt、shift、meta是系统修饰键,配合keydown可以正常使用。但是如果配合keyup事件,需要按下修饰键的同时,再按下其他键,随后释放其他键,事件才能被触发。

methods中的this:

  1. <body>
  2. <div id="app">
  3. <button v-on:click="showInfo">提示信息</button>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip = false;
  8. const vm = new Vue({
  9. el: '#app',
  10. methods: {
  11. // 此处不建议使用箭头函数,因为如果使用箭头函数则this变为window,而不是Vue实例。
  12. // 如果是组件,那么this就是组件。使用了箭头函数就不再指向组件就会报错。
  13. showInfo(event) { // 和普通的绑定事件函数一样,该函数也有一个默认event事件参数
  14. console.log(event.target.innerHTML); // 可以通过event事件获取相关内容
  15. console.log(this); // 此处的this是Vue实例
  16. }
  17. }
  18. });
  19. </script>

methods中定义的函数最终也会被加进vm对象属性上。

所以,理论上,把showInfo写在data中也可以正常运行:

  1. const vm = new Vue({
  2. el: '#app',
  3. data: { // 把方法写在data中也可以正常运行
  4. showInfo(event) {
  5. console.log(event.target.innerHTML);
  6. console.log(this);
  7. }
  8. }
  9. });

但是不推荐这么做。因为data中的内容vue是需要做数据代理的,但是methods中的内容不需要做数据代理也能运行。如果把函数写在data中,就会消耗资源让vue对函数做了没有意义的数据代理。

v-text 和 v-html

传统js的innerTextinnerHTML

  1. window.onload = function () {
  2. // innerText会将<h1>作为字符串输出
  3. document.getElementById("div1").innerText = '<h1>text</h1>';
  4. // innerHTML会解析<h1>,将innerHTML字符串加粗
  5. document.getElementById("div2").innerHTML = '<h1>innerHTML</h1>';
  6. }

vue里面使用v-textv-html进行处理:

  1. <div id="app">
  2. <!-- 功能类似innerText -->
  3. <div v-text="message"></div>
  4. <!-- 功能类似innerHTML -->
  5. <div v-html="message"></div>
  6. </div>
  7. <script>
  8. new Vue({
  9. el: "#app",
  10. data: {
  11. message: "<h1>text</h1>"
  12. }
  13. });
  14. </script>

v-bind

插值语法不能作用在HTML特性上,遇到这种情况应该使用v-bind指令。

例如:将html的color属性设置成变量

  1. <!-- 在color属性里面使用插值表达式 不会 生效 -->
  2. <font size="5" color="{{myColor}}">text</font>

想要给Html标签属性设置变量,需要使用v-bind指令:

  1. <body>
  2. <div id="app">
  3. <font size="5" v-bind:color="myColor1">text1</font>
  4. <font size="5" v-bind:color="myColor2">text2</font>
  5. </div>
  6. </body>
  7. <script>
  8. new Vue({
  9. el: '#app',
  10. data: {
  11. myColor1: "red",
  12. myColor2: "green"
  13. }
  14. });
  15. </script>

v-bind指令也可以进行简写:

  1. <!-- 完整写法 -->
  2. <font size="5" v-bind:color="myColor2">text2</font>
  3. <!-- 简写 -->
  4. <font size="5" :color="myColor2">text2</font>

绑定class属性时,普通的class和v-bind:class可以自动合并:

  1. <!-- 如果a变量的值为normal,则最终生成的class会自动合并为:class='basic normal' -->
  2. <div class="basic" :class="a"></div>
  3. <!-- class绑定的变量a可以是数组,将数组中的每一项都加到class中 -->
  4. <script>
  5. new Vue({
  6. data: {
  7. a: ['test1', 'test2', 'test3']
  8. }
  9. })
  10. </script>
  11. <!-- 也可以直接在绑定变量的位置写数组 -->
  12. <div class='basic' :class='["test1", "test2", "test3"]'></div>
  13. <!-- 也可以在绑定变量的写数组变量(变量名不加引号,加了引号就是字符串) -->
  14. <div class='basic' class='[a, b, c]'></div>
  15. <script>
  16. new Vue({
  17. data: {
  18. a: 'test1',
  19. b: 'test2',
  20. c: 'test3'
  21. }
  22. })
  23. </script>

绑定class的对象写法:

  1. <!-- class绑定的变量是一个对象,对象内部属性是样式名称 -->
  2. <div class='basic' :class="classObj"></div>
  3. <script>
  4. new Vue({
  5. data: {
  6. classObj: {
  7. test1: true, // 使用test1样式
  8. test2: false // 不使用test2样式
  9. }
  10. }
  11. });
  12. </script>
  13. <!-- 也可以直接在class上绑定 -->
  14. <div class='basic' :class="{test1:true, test2:false}"></div>

v-bind绑定style:

  1. <body>
  2. <div id="app">
  3. <!-- 原始html写法 -->
  4. <div id="basic2" style="font-size:40px;">aaa</div>
  5. <!-- vue写法 -->
  6. <!-- style加上大括号做成对象,font-size换成小驼峰写法 -->
  7. <div id="basic" :style="{fontSize: fsize + 'px'}">aaa</div>
  8. </div>
  9. </body>
  10. <script>
  11. const vm = new Vue({
  12. el: '#app',
  13. data: {
  14. fsize: 40
  15. }
  16. });
  17. </script>

也可以写成:

  1. <body>
  2. <div id="app">
  3. <!-- 将样式绑定到变量 -->
  4. <div id="basic" :style="styleObj">aaa</div>
  5. </div>
  6. </body>
  7. <script>
  8. const vm = new Vue({
  9. el: '#app',
  10. data: {
  11. // 将样式变量写成对象形式
  12. styleObj: {
  13. // 属性名使用小驼峰写法
  14. fontSize: '40px',
  15. color:'red',
  16. backgroundColor:'orange'
  17. }
  18. }
  19. });
  20. </script>

style数组写法:

  1. <body>
  2. <div id="app">
  3. <!-- 使用数组形式指定多个样式对象 -->
  4. <div id="basic" :style="[styleObj, styleObj2]">aaa</div>
  5. </div>
  6. </body>
  7. <script>
  8. const vm = new Vue({
  9. el: '#app',
  10. data: {
  11. styleObj: {
  12. fontSize: '40px'
  13. }
  14. styleObj2: {
  15. color:'red',
  16. backgroundColor:'orange'
  17. }
  18. });
  19. </script>

v-model

v-bind是单向的数据绑定:

  1. <!-- v-bind可以将vue中的变量绑定到标签属性上,但是标签值变化时不能更新vue中变量的值 -->
  2. <input type="text" v-bind:value="user.username"> <br>

使用v-model进行对象属性双向绑定:

v-model只能用在表单类输入元素上。

v-model:value可以简写为v-model,因为v-model收集的就是value属性值。

  1. <body>
  2. <div id="app">
  3. <form action="" method="post">
  4. 用户名: <input type="text" v-model:value="user.username"> <br>
  5. <!-- v-model:value可以简写成v-model -->
  6. 密码: <input type="text" v-model="user.password"> <br>
  7. </form>
  8. </div>
  9. </body>
  10. <script>
  11. new Vue({
  12. el: '#app',
  13. data: {
  14. user: {
  15. username: 'tom',
  16. password: '123456'
  17. }
  18. }
  19. });
  20. </script>

v-for

使用v-for遍历数组:

  1. <body>
  2. <div id="app">
  3. <!-- 遍历字符串数组 -->
  4. <li v-for="(item) in list1">{{item}}</li>
  5. <!-- 遍历对象数组 -->
  6. <li v-for="(item) in list2">{{item.username + ":" + item.age}}</li>
  7. </div>
  8. </body>
  9. <script>
  10. new Vue({
  11. el: '#app',
  12. data: {
  13. list1: ['tom', 'jane', 'marry'],
  14. list2: [
  15. {username: 'tom', age: 10},
  16. {username: 'jane', age: 30},
  17. {username: 'marry', age: 18},
  18. ]
  19. }
  20. });
  21. </script>

也可以遍历成2个参数,第1个参数为项目值,第2个参数为在数组中的下标:

  1. <li v-for="(item, index) in list1">{{index + ": " + item}}</li>

遍历对象:

  1. <body>
  2. <div id="app">
  3. <!-- 第1个参数为值,第2个参数为key -->
  4. <li v-for="(value, key) in list3">{{key + ":" + value}}</li>
  5. </div>
  6. </body>
  7. <script>
  8. new Vue({
  9. el: '#app',
  10. data: {
  11. list3: {
  12. id: 1,
  13. name: 'tom',
  14. age: 19
  15. }
  16. }
  17. });
  18. </script>

遍历字符串:

  1. <div id="app">
  2. <ul>
  3. <li v-for="(char, index) in str">{{index}}:{{char}}</li>
  4. </ul>
  5. </div>
  6. <script>
  7. const vm = new Vue({
  8. data: {
  9. str: "hello"
  10. }
  11. });
  12. </script>

遍历指定次数:

  1. <!-- 遍历5次:value为从1开始递增的数字,index为从0开始递增的数字 -->
  2. <li v-for="(value,index) in 5">{{index}}:{{value}}</li>

双层循环:

  1. <body>
  2. <div id="app">
  3. <table>
  4. <tr>
  5. <td>序号</td>
  6. <td>名称</td>
  7. <td>年龄</td>
  8. </tr>
  9. <!-- 第一层循环,遍历每个学生 -->
  10. <tr v-for="(item, index) in list2">
  11. <td>{{index}}</td>
  12. <!-- 第2层循环,遍历学生的每个属性 -->
  13. <td v-for="(value, key) in item">{{key + ":" + value}}</td>
  14. </tr>
  15. </table>
  16. </div>
  17. </body>
  18. <script>
  19. new Vue({
  20. el: '#app',
  21. data: {
  22. list2: [
  23. {username: 'tom', age: 10},
  24. {username: 'jane', age: 30},
  25. {username: 'marry', age: 18},
  26. ]
  27. }
  28. });
  29. </script>

v-for为每个数据添加key:

  1. <body>
  2. <div id="app">
  3. <h2>人员列表</h2>
  4. <ul>
  5. <!-- 为列表项动态绑定key -->
  6. <li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
  7. </ul>
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip = false;
  12. const vm = new Vue({
  13. el: '#app',
  14. data: {
  15. persons: [
  16. {
  17. id: 1,
  18. name: '张三',
  19. age: 18
  20. },
  21. {
  22. id: 2,
  23. name: '李四',
  24. age: 20
  25. },
  26. {
  27. id: 3,
  28. name: '王五',
  29. age: 30
  30. }
  31. ]
  32. }
  33. });
  34. </script>

也可以将索引值定义为key:

  1. <!-- v-for第二个参数为index,可以将索引值定义为Key -->
  2. <li v-for="(p,i) in persons" :key="i">{{p.name}}-{{p.age}}</li>

Key的内部原理:

在虚拟DOM中,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是没有问题的。

v-for标签中没有写key时,vue会默认使用index作为key。

v-for里面可以使用of代替in,效果一样:

  1. <!-- in 和 of 效果完全一样 -->
  2. <li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
  3. <li v-for="p of persons" :key="p.id">{{p.name}}-{{p.age}}</li>

示例:列表过滤并排序:

  1. <body>
  2. <div id="app">
  3. <h2>列表过滤并排序</h2>
  4. <input type="text" placeholder="请输入名字" v-model="keyWord">
  5. <button @click="sortType = 1">年龄升序</button>
  6. <button @click="sortType = 2">年龄降序</button>
  7. <button @click="sortType = 0">原顺序</button>
  8. <ul>
  9. <li v-for="(p,index) of fillPersons">
  10. {{p.name}}-{{p.age}}-{{p.sex}}
  11. </li>
  12. </ul>
  13. </div>
  14. </body>
  15. <script>
  16. Vue.config.productionTip = false;
  17. const vm = new Vue({
  18. el: '#app',
  19. data: {
  20. keyWord:'',
  21. sortType:0, // 0:原顺序,1:升序,2:降序
  22. persons: [
  23. {id:'001', name:'马冬梅', age: 19, sex:'女'},
  24. {id:'002', name:'周冬雨', age: 20, sex:'女'},
  25. {id:'004', name:'温兆伦', age: 22, sex:'男'},
  26. {id:'003', name:'周杰伦', age: 21, sex:'男'}
  27. ]
  28. },
  29. computed: {
  30. fillPersons() {
  31. const arr = this.persons.filter((p) => {
  32. return p.name.indexOf(this.keyWord) !== -1;
  33. });
  34. if(this.sortType) {
  35. arr.sort((a,b) => {
  36. return this.sortType === 1 ? b.age-a.age : a.age-b.age;
  37. });
  38. }
  39. return arr;
  40. }
  41. }
  42. });
  43. </script>

v-if

条件渲染指令:v-ifv-else-ifv-elsev-show

v-show做条件渲染,判断是否展示该标签:

  1. <!-- v-show中使用布尔值 -->
  2. <h2 v-show='true'>aaa</h2>
  3. <!-- v-show使用表达式 -->
  4. <h2 v-show='1 == 2'>aaa</h2>
  5. <!-- v-show绑定变量 -->
  6. <h2 v-show='a'>aaa</h2>
  7. <script>
  8. new Vue({
  9. data: {
  10. a: true
  11. }
  12. });
  13. </script>

v-if做条件渲染:

  1. <!-- v-if中使用布尔值 -->
  2. <h2 v-if='true'>aaa</h2>
  3. <!-- v-if也可以使用表达式、变量 -->

v-if如果为false时,该标签不再渲染出来。v-show为false时,会将该标签设置为display:none

如果变量的值变化频繁,建议使用v-show,因为v-show的标签已经渲染出来,只是设置了display属性是否展示。

else的用法:

  1. <div v-if="n === 1">
  2. Angular
  3. </div>
  4. <div v-else-if="n === 2">
  5. React
  6. </div>
  7. <div v-else-if="n === 3">
  8. Vue
  9. </div>
  10. <div v-else>
  11. abc
  12. </div>

一组v-ifv-else-ifv-else必须紧紧挨在一起,不能被打断:

下面的代码会报错:

  1. <div v-if="n === 1">Angular</div>
  2. <div v-else-if="n === 2">React</div>
  3. <!-- if else 被打断,后面的else不能被解析,控制台也将报错 -->
  4. <div>aaaa</div>
  5. <div v-else>abc</div>

template标签

使用<template>标签简写代码:

  1. <!-- 以下代码重复判断比较繁琐 -->
  2. <h2 v-if="n === 1">hello</h2>
  3. <h2 v-if="n === 1">aaa</h2>
  4. <h2 v-if="n === 1">bbb</h2>
  5. <!-- 可以简写为 -->
  6. <!-- 如果使用div包裹,会破坏原来的标签结构。使用template不会破坏标签结构 -->
  7. <template v-if="n === 1">
  8. <h2>hello</h2>
  9. <h2>aaa</h2>
  10. <h2>bbb</h2>
  11. </template>

<template>只能和v-if配合使用,不能写v-show

v-cloak

在标签上加上的v-cloak指令,会在vue接管该标签时删除该指令。

用途:如果src引入的vue网速较慢,可以使用v-cloak配合css让该标签暂时不显示。

例如:

  1. <html>
  2. <head>
  3. <style>
  4. [v-clock] { // 获取带有v-clock属性的标签
  5. display: none
  6. }
  7. </style>
  8. </head>
  9. <body>
  10. <div id='app'>
  11. <!-- vue.js没有加载出来时,h2标签上会带有v-cloak属性。当vue接管该区域时,v-cloak属性会自动删除 -->
  12. <h2 v-cloak>{{name}}</h2>
  13. </div>
  14. <script src="http://xxxx/vue.js"></script>
  15. </body>
  16. <script>
  17. new Vue({
  18. el:'#app',
  19. data:{
  20. name:'tom'
  21. }
  22. });
  23. </script>
  24. </html>

v-once

v-once所在节点在初次动态渲染后,就视为静态内容了。以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

例如:

  1. <h2 v-once> n的初始值:{{n}} </h2>
  2. <h2> n的当前值:{{n}} </h2>
  3. <button @click="n++"> n+1 </button>

点击n+1按钮后,n的当前值会+1,但是v-once所在标签不再动态更新,依然显示的n初始值。

v-pre

v-pre指令可以让vue跳过其所在节点的编译过程。可以利用该指令跳过没有使用指令语法、没有使用插值语法的节点,会加快编译。

例如:

  1. <!-- 正常显示aaa -->
  2. <h2 v-pre>aaa</h2>
  3. <!-- 不再编译为n值,而是直接显示{{n}} -->
  4. <h2 v-pre> {{n}} </h2>
  5. <!-- 不再将@click编译为绑定事件,而是在标签显示属性@click -->
  6. <button v-pre @click="n++">n+1</button>

el 的不同写法

elelement的意思,即获取element对象。

el可以赋值一个选择器,例如:id选择器#app、class选择器.app,还可以直接赋值dom对象document.getElementById('#app')

第一种写法:

  1. <div id='app'>
  2. {{name}}
  3. </div>
  4. <script>
  5. new Vue({
  6. el: '#app', // 在创建Vue实例时就直接指定接管的dom对象
  7. data: {
  8. name: 'tom'
  9. }
  10. });
  11. </script>

第二种写法:

  1. <div id='app'>
  2. {{name}}
  3. </div>
  4. <script>
  5. const vm = new Vue({
  6. data: {
  7. name: 'tom'
  8. }
  9. });
  10. // 打印出来的vm对象中,美元符$开头的属性是Vue提供给开发人使用的;下划线_开头的属性是Vue底层用到的
  11. console.log(vm);
  12. // 利用VM对象的$mount属性绑定接管的dom对象
  13. // $mount属性不是vm直接带有的,而是创建vm对象的Vue的,可以通过原型链找到该属性
  14. // 这种方式可以更灵活的绑定需要接管的dom对象
  15. vm.$mount('#app');
  16. </script>

为什么是$mount属性:Vue代码运行之后,得到的name变量和值存储在vm内,需要将其“挂载”到页面上,$mount即指定“挂载”的位置。

data的不同写法

第一种写法:(对象式)

  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. name: 'tom'
  5. }
  6. });

第二种写法:(函数式)

  1. const vm = new Vue({
  2. el: '#app',
  3. data: function() {
  4. // 如果此处是用的function定义的函数,那么此处的this是Vue实例对象
  5. // 但是如果此处是使用的 箭头函数形式 缩写,那么此处的this获取到的是window对象。因为箭头函数没有自己的this,只能向上找,向上就找到了window对象
  6. // data: ()=> { // 这样使用箭头函数获取到的this是window,在使用组件时有影响,要避免这种写法
  7. // data(){ // 可以这样简写
  8. console.log(this);
  9. return {
  10. name: 'tom'
  11. };
  12. }
  13. });

或者:

  1. function getData() {
  2. return {
  3. name: 'tome'
  4. }
  5. }
  6. const vm = new Vue({
  7. el: '#app',
  8. data: getData
  9. });

只要是Vue管理的函数,一定不要写成箭头函数,否则this就不是Vue实例了。

插值表达式可以绑定的其他变量

  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. name: 'tom',
  5. age: 18
  6. }
  7. });
  8. console.log(vm);

new Vue返回的Vue实例,就对应到MVVM模型的ViewModel,所以一般将这个变量名简写为vm

我们编码写在data中的数据,最后都出现在了vm属性里(通过数据代理)。

所有vm上的属性也都可以直接使用插值语法绑定到页面模板里:

  1. <!-- 绑定vm的$options属性 -->
  2. <div> {{ $options }} </div>

不只是vm上的属性,包括创建vm的Vue上的属性也可以通过原型链在vm上找到,所以也可以进行绑定:

  1. <!-- 绑定vm原型链上的属性 -->
  2. <div>{{$emit}}</div>