Vue模板语法

一. Vue概述

尤雨溪:Vue.js的创建者

  • 2016年5月,Vue2发布
  • 2020年9月,Vue3发布

Vue: (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架

渐进式框架就是,我们可以在项目中一点点来引入Vue,而不一定需要全部使用Vue来开发整个项目。

官网:https://cn.vuejs.org/v2/guide/

  • 易用:熟悉HTML、CSS、JavaScript知识后,可快速上手Vue
  • 灵活:Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
  • 高效:20kB运行大小,超快虚拟 DOM

注意:下面我们介绍的是Vue2.x版本的。

二. 开发模式对比

原生JS:

<div id="msg"></div>
<script type="text/javascript">
    var msg = 'Hello World';
    var div = document.getElementById('msg');
    div.innerHTML = msg;
</script>

jQuery:

<div id="msg"></div>
<script type="text/javascript" src="js/jquery.js"></script> 
<script type="text/javascript">
    var msg = 'Hello World';
    $('#msg').html(msg);
</script>

Vue.js之HelloWorld实现:

使用Vue将 helloworld 渲染到页面上:

  1. 实例参数分析
    el:元素的挂载位置(值可以是CSS选择器或者DOM元素)
    data:模型数据(值是一个对象)
  2. 插值表达式用法
    将数据填充到HTML标签中
    插值表达式支持基本的计算操作
  3. Vue代码运行原理分析
    概述编译过程的概念(Vue语法 → 原生语法)

三. Vue模板语法

1 - 前端渲染

前端渲染就是把数据填充到HTML标签中。

前端渲染有如下三种方式:

  • 原生js拼接字符串
  • 使用前端模板引擎
  • 使用vue特有的模板语法

1. 原生js拼接字符串

基本上就是将数据以字符串的方式拼接到HTML标 签中,前端代码风格大体上如下所示。

var d = data.weather;
var info = document.getElementById('info');
info.innerHTML = '';
for(var i=0;i<d.length;i++){
    var date = d[i].date;
    var day = d[i].info.day;
    var night = d[i].info.night;
    var tag = '';
    tag += '<span>日期:'+date+'</sapn><ul>';
    tag += '<li>白天天气:'+day[1]+'</li>'
    tag += '<li>白天温度:'+day[2]+'</li>'
    tag += '<li>白天风向:'+day[3]+'</li>'
    tag += '<li>白天风速:'+day[4]+'</li>'
    tag += '</ul>';
    var div = document.createElement('div');
    div.innerHTML = tag;
    info.appendChild(div);
}

缺点:不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来。

2. 使用前端模板引擎

如下代码是基于模板引擎art-template的一段代码,与拼接字符串相比,代码明显规范了很多,它拥有自己的一套模板语法规则。

<script id="abc" type="text/html">
    {{if isAdmin}}
    <h1>{{title}}</h1>
    <ul>
        {{each list as value i}}
            <li>索引 {{i + 1}} :{{value}}</li>
        {{/each}}
    </ul>
    {{/if}}
</script>

优点:大家都遵循同样的规则写代码,代码可读性明显提高了,方便后期的维护。
缺点:没有专门提供事件机制。

3. 使用Vue模板语法

第三种方式就是使用Vue模板语法了,下面我们详细讲述一下Vue模板语法。

2 - 指令

  • 指令的本质就是自定义属性
  • 指令的格式:以v-开始(比如:v-cloak)

1. v-cloak指令

  • 插值表达式存在的问题:“闪动”
    原因:Vue会先把 {{}} 显示在页面中,然后再迅速替换成具体的值,所以会有闪动问题
  • 如何解决该问题:使用v-cloak指令
  • 解决该问题的原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果
 <style type="text/css">
  /* 
    1、通过属性选择器选择带有属性v-cloak的标签,让他隐藏
 */
  [v-cloak]{
    /* 元素隐藏  */
    display: none;
  }
  </style>
<body>
  <div id="app">
    <!-- 2、 让带有插值语法的标签添加 v-cloak 属性,在数据渲染完之后,v-cloak属性会被自动去除,v-cloak一旦移除也就是没有这个属性了,属性选择器就选择不到该标签,也就是对应的标签会变为可见
    -->
     <!-- 背后的原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果 -->
    <div v-cloak >{{msg}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      //  el:指定元素id是app的元素  
      el: '#app',
      //  data:里面存储的是数据,是个对象
      data: {
        msg: 'Hello Vue'
      }
    });
</script>
</body>
</html>

虽然v-cloak指令可以解决闪动的问题,但是我们很少用,因为闪动就闪动吧,很少管,不管也没事。

2. v-text 填充纯文本

  • v-text指令用于将数据填充到标签中,作用和插值表达式类似,但是没有闪动问题
  • 如果数据中有HTML标签会将html标签一并输出
  • 注意:此处为单向绑定,数据对象上的值改变,插值会发生变化;但是当插值发生变化并不会影响数据对象的值
<div id="app">
    <!--  
        注意:在指令中不要写插值语法,直接写对应的变量名
    -->
    <p v-text="msg"> </p>
    <p>
        <!-- Vue中只有在标签的内容中,才用插值语法 -->
        {{msg}}
    </p>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        }
    });
</script>

很少用,我们一般还是用插值表达式。

3. v-html 填充HTML片段

  • 用法和v-text 相似,但是他可以将HTML片段填充到标签中
  • 有安全问题:一般只在可信任内容上使用 v-html永不用在用户提交的内容上
  • 它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。
<div id="app">
  <p v-html="html"></p> <!-- 输出:html标签在渲染的时候被解析 -->
    
    <p>{{message}}</p> <!-- 输出:<span>通过双括号绑定</span> -->
    
  <p v-text="text"></p> <!-- 输出:<span>html标签在渲染的时候被源码输出</span> -->
</div>
<script>
  let app = new Vue({
  el: "#app",
  data: {
    message: "<span>通过双括号绑定</span>",
    html: "<span>html标签在渲染的时候被解析</span>",
    text: "<span>html标签在渲染的时候被源码输出</span>",
  }
 });
</script>

4. v-pre 填充原始信息

  • 显示原始信息,跳过编译过程
  • 跳过这个元素和它的子元素的编译过程。
  • 一些静态的内容不需要编译加这个指令可以加快渲染
<span v-pre>{{ this will not be compiled }}</span>    
<!--  显示的是:{{ this will not be compiled }}  -->
<span v-pre>{{msg}}</span>  
<!--  即使data里面定义了msg这里仍然是显示的:{{msg}}  -->
<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        }
    });
</script>

加快渲染的指令,也很少用。

5. v-once 只编译一次

执行一次性的插值(当数据改变时,插值处的内容不会继续更新)

<!-- 即使data里面定义了msg,后期我们修改了msg,仍然显示的是第一次data里面存储的数据即 Hello Vue.js  -->
<span v-once>{{msg}}</span>    
<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        }
    });
</script>

上面我们讲的数据插值,以及上面几个指令都是数据绑定,都是响应式的(数据的变化导致页面内容的变化)。

3 - 双向数据绑定指令

1. 什么是双向数据绑定?

  • 当数据发生变化的时候,视图也就发生变化
  • 当视图发生变化的时候,数据也会跟着同步变化

2. v-model 双向数据绑定

v-model是一个指令,限制在 <input>、<textarea>、<select>、components中使用。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <div>
      <!-- 当输入框中内容改变的时候,下面的msg会自动更新 -->
      <input type="text" v-model='msg'>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      双向数据绑定
      1、从页面到数据
      2、从数据到页面
    */
    var vm = new Vue({
      el: '#app',
      data: {
        // 当这里的msg改变的时候,上面输入框的值也会自动更新
        msg: 'Hello Vue'
      }
    });
  </script>
</body>
</html>

3. MVVM设计思想

MVC 是后端的分层开发概念,MVVM是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端的视图层,分为了三部分 Model、View、 ViewModel。

① M(model) 数据层 Vue中数据层都放在 data 里面
② V(view) 视图 Vue中 view 即我们的 HTML 页面
③ VM(View-Model) 控制器 将数据和视图层建立联系,vm 即 Vue 的实例

4 - 事件绑定

1. v-on: 事件绑定

用来绑定事件的,形式如:v-on:click 缩写为 @click。

2. 事件函数的绑定方式

  1. 直接绑定函数名称
<button v-on:click='say'>Hello</button>  
  1. 绑定调用函数(虽然写的是say(),并不会调用函数,只有点击的时候才会调用函数),很少用
<button v-on:click='say()'>Say hi</button>

3. 事件函数中传入参数

  • 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的参数
  • 如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
<body>
    <div id="app">
        <div>{{num}}</div>
        <div>
            <!-- 1、如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的参数 -->
            <button v-on:click='handle1'>点击1</button>
            <!-- 2、如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event -->
            <button v-on:click='handle2(123, 456, $event)'>点击2</button>
        </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                num: 0
            },
            methods: {
                // 默认有事件对象
                handle1: function(event) {
                    console.log(event.target.innerHTML)
                },
                // 事件对象作为最后一个参数
                handle2: function(p, p1, event) {
                    console.log(p, p1)
                    console.log(event.target.innerHTML)
                    this.num++;
                }
            }
        });
    </script>

一般我们直接绑定函数名称,不传参数,因为基本上所有的数据都在data()中,我们可以直接拿,不用传递。

4. 事件修饰符

  • 在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求
  • Vue 不推荐我们操作DOM,为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符,主要包括:.stop.prevent.self
  • 修饰符是由点开头的指令后缀来表示的
<div>{{num}}</div>
<div v-on:click='handle0'>
  <!-- 阻止冒泡,如果不阻止,点击按钮的时候通过冒泡的形式handle0也会触发,num值也会增加 -->
  <button v-on:click.stop='handle1'>点击1</button>
</div>

<!-- 阻止默认行为 -->
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!--  
    handle2: function(event){
      // 原来的阻止默认行为
      // event.preventDefault();
  }
-->

<!-- 修饰符可以串联,即阻止冒泡也阻止默认事件 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只当在 event.target 是当前元素自身时才会触发处理函数(就是点击的是自己) -->
<!-- 即事件不是从内部元素触发的(就是不是冒泡出来的) -->
<div v-on:click.self="doThat">...</div>

5. 按键修饰符

在做项目中有时会用到键盘事件,在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符,如:keyup.enterkeydown.space,其中keyup是弹起时触发,keydown是按下时触发。

<!-- 当enter弹起时,调用 vm.submit() -->
<input v-on:keyup.enter="submit">

<!-- 当delete或者space弹起时,调用 vm.alertMe()  -->
<input v-on:keyup.delete.space="alertMe" >

<!-- 当keyCode是13的按键弹起时,调用 vm.submit() -->
<input v-on:keyup.13="submit">

<!-- 
常用的按键修饰符
.enter =>    enter键
.tab => tab键
.delete (捕获“删除”和“退格”按键) =>  删除键
.esc => 取消键
.space =>  空格键
.up =>  上
.down =>  下
.left =>  左
.right =>  右
-->

<script>
    var vm = new Vue({
        el:"#app",
        methods: {
              submit:function(){},
              alertMe:function(){},
        }
    })
</script>

6. 自定义按键修饰符别名

在Vue中可以通过 Vue.config.keyCodes 自定义按键修饰符别名。

<div id="app">
    <!-- 由于预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法 -->
    <input type="text" v-on:keydown.f5="prompt()">
</div>

<script>
  
    // 自定义按键修饰符别名
    // 名字是自定义的,但是对应的值必须是按键对应event.keyCode值
    Vue.config.keyCodes.f5 = 116;

    let app = new Vue({
        el: '#app',
        methods: {
            prompt: function() {
                alert('我是 F5!');
            }
        }
    });
</script>

7. 案例:简单计算器

需求:实现简单的加法计算,分别输入数值a和数值b,点击计算按钮,结果显示在下面。

  1. 通过v-model指令实现数值a和数值b的绑定
  2. 给计算按钮绑定事件,实现计算逻辑
  3. 将计算结果绑定到对应位置
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h1>简单计算器</h1>
    <div>
      <span>数值A:</span>
      <span>
        <input type="text" v-model='a'>
      </span>
    </div>
    <div>
      <span>数值B:</span>
      <span>
        <input type="text" v-model='b'>
      </span>
    </div>
    <div>
      <button v-on:click='handle'>计算</button>
    </div>
    <div>
      <span>计算结果:</span>
      <!-- 使用v-text,数据响应式 -->
      <span v-text='result'></span>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      简单计算器案例 
    */
    var vm = new Vue({
      el: '#app',
      data: {
        a: '',
        b: '',
        result: ''
      },
      methods: {
        handle: function(){
          // 实现计算逻辑
          this.result = parseInt(this.a) + parseInt(this.b);
        }
      }
    });
  </script>
</body>
</html>

5 - 属性绑定

1. v-bind: 响应地更新html属性

  • v-bind:指令被用来响应地更新 HTML 属性
  • v-bind:可以缩写为:,所以 v-bind:href 可以缩写为 :href
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <!-- 绑定一个属性 -->
    <a v-bind:href="url">百度</a>
    <!-- 缩写 -->
    <a :href="url">百度1</a>
    <button v-on:click='handle'>切换</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /* 属性绑定 */
    var vm = new Vue({
      el: '#app',
      data: {
        url: 'http://www.baidu.com'
      },
      methods: {
        handle: function(){
          // 修改URL地址
          this.url = 'http://itcast.cn';
        }
      }
    });
  </script>
</body>
</html>

2. v-model的底层实现原理分析

v-model的底层就是通过绑定value属性,然后通过监听input事件来处理值的变化。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    // v-model的底层实现原理
    <input type="text" v-bind:value="msg" v-on:input='handle'>
    // v-model的底层实现原理:简写如下
    <input type="text" v-bind:value="msg" v-on:input='msg=$event.target.value'>
    // v-model双向数据绑定
    <input type="text" v-model='msg'>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /* v-model指令的本质 */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'hello'
      },
      methods: {
        handle: function(event){
          // 使用输入域中的最新的数据覆盖原来的数据
          this.msg = event.target.value;
        }
      }
    });
  </script>
</body>
</html>

6 - 样式绑定

1. class样式绑定

① 绑定对象语法

  • 我们可以给 v-bind:class 一个对象,以动态地切换class。
  • 注意:v-bind:class 指令可以与普通的class特性共存
  • 绑定对象的时候,对象的属性名就是要渲染的类名,对象的属性值对应的是 data 中的数据,即是否要渲染这个类,是个布尔值。
  • 我们也可以绑定一个返回对象的计算属性,这是很常用。
<div v-bind:class="{ active: isActive }"></div>
/* 
  1. v-bind 中支持绑定一个对象 
  如果绑定的是一个对象,则键为对应的类名 值为对应data中的数据 
    HTML最终渲染为 <ul class="box textColor textSize"></ul>
    注意:
        textColor,textSize  对应的渲染到页面上的CSS类名 
        isColor,isSize  对应vue data中的数据  如果为true 则对应的类名渲染到页面上 
        当 isColor 和 isSize 变化时,class列表将相应的更新,
        例如,将isSize改成false,
        class列表将变为 <ul class="box textColor"></ul>
*/
// v-bind:class
<ul class="box" v-bind:class="{textColor:isColor, textSize:isSize}">
    <li>学习Vue</li>
    <li>学习Node</li>
    <li>学习React</li>
</ul>
<button v-on:click='handle'>切换</button>
<script>
    var vm = new Vue({
        el:'.box',
        data:{
            isColor:true,
            isSize:true,
        },
        methods: {
          handle: function(){
            // 控制isColor的值在true和false之间进行切换
            this.isColor = !this.isColor;
            this.isSize = !this.isSize;
          }
        }
    })
</script>

② 绑定数组语法

绑定数组的时候,数组里面存的是需要渲染的类名,就是 data 中的数据。

<div v-bind:class="[colorClass, sizeClass]"></div>
/* 
  2. v-bind 中支持绑定一个数组    
  数组中colorClass 和 sizeClass 对应为data中的数据
  这里的colorClass 对用data 中的  textColor
  这里的sizeClass  对用data 中的  textSize
*/
<ul class="box" :class="[colorClass, sizeClass]">
    <li>学习Vue</li>
    <li>学习Node</li>
    <li>学习React</li>
</ul>
<button v-on:click='handle'>切换</button>
<script>
var vm= new Vue({
    el:'.box',
    data:{
        colorClass:'textColor',
        sizeClass:'textSize'
    },
    methods: {
      handle: function(){
        this.colorClass = '';
        this.sizeClass = '';
    }
  }
})
</script>

③ class样式绑定语法细节

  1. 对象绑定和数组绑定可以结合使用
  2. class绑定的值可以简化传入对象名或数组名
  3. 默认的class会保留,不会被覆盖
  4. v-bind:可以缩写为:,所以v-bind:class可以简写为:class
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: orange;
    }
    .test {
      color: blue;
    }
    .base {
      font-size: 28px;
    }
  </style>
</head>
<body>
  <div id="app">
    // 1、对象绑定和数组绑定可以结合使用
    <div v-bind:class='[activeClass, errorClass, {test: isTest}]'>测试样式</div>
    // 2、class绑定的值可以简化操作
    // 对象简化,传入对象名
    <div v-bind:class='objClasses'></div>
    // 数组简化,传入数组名
    <div v-bind:class='arrClasses'></div>
    // 3、默认的class会保留,不会被覆盖
    <div class="base" v-bind:class='objClasses'></div>
    // 4、v-bind:class 可以简写为 :class
    <div :class='objClasses'></div>
    <button v-on:click='handle'>切换</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'error',
        isTest: true,
        arrClasses: ['active','error'],
        objClasses: {
          active: true,
          error: true
        }
      },
      methods: {
        handle: function(){
          // this.isTest = false;
          this.objClasses.error = false;
        }
      }
    });
  </script>
</body>
</html>

2. style样式绑定

  • 对象语法
<div v-bind:style="{color: activeColor, fontSize: fontSize}"></div>
  • 数组语法
<div v-bind:style="[styleObj1, styleObj2]"></div>
// 绑定样式对象: 传入对象
// CSS属性名可以用驼峰式或短横线分隔
<div v-bind:style="{color: activeColor, fontSize: fontSize, background:'red' }">内联样式</div>

// 绑定样式对象: 传入对象名
<div v-bind:style="styleObject">绑定样式对象</div>'

// 绑定样式: 传入对象数组
// 组语法可以将多个样式对象应用到同一个元素
// 如果样式对象中有相同的属性,后面的会覆盖前面的
<div v-bind:style="[styleObj1, styleObj2]"></div>
// v-bind: 可以缩写为 :
<div :style="[styleObj1, styleObj2]"></div>

<script>
    new Vue({
      el: '#app',
      data: {
        activeColor: 'green',
        fontSize: "30px"
        styleObject: {
          color: 'green',
          fontSize: '30px',
          background:'red'
        },
        styleObj1: {
          color: 'red'
        },
        styleObj2: {
            fontSize: '30px'
        }
      }
   });
</script>

7 - 分支循环结构

1. v-if

通过条件判断是否渲染某个元素。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div v-if='score>=90'>优秀</div>
    <div v-else-if='score<90&&score>=80'>良好</div>
    <div v-else-if='score<80&&score>60'>一般</div>
    <div v-else>比较差</div>
    <div v-show='flag'>测试v-show</div>
    <button v-on:click='handle'>点击</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      v-show的原理:控制元素样式是否显示 display:none
    */
    var vm = new Vue({
      el: '#app',
      data: {
        score: 10,
        flag: false
      },
      methods: {
        handle: function(){
          this.flag = !this.flag;
        }
      }
    });
  </script>
</body>
</html>

2. v-if与v-show的区别

  • v-if是动态的向DOM树内添加或者删除DOM元素,v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件。
  • v-show本质就是标签display设置为none,控制隐藏。v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。

3. 循环结构

① v-for遍历数组

用于循环的数组里面的值可以是对象,也可以是普通元素。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div>水果列表</div>
    <ul>
      <!-- 遍历数组(数组里面是字符串) -->
      <li v-for='item in fruits'>{{item}}</li>
      <!-- 遍历数组(数组里面是字符串),有index -->
      <li v-for='(item, index) in fruits'>{{item + '---' + index}}</li>
      <!-- 遍历数组(数组里面是对象) -->
      <!-- :key的作用:帮助Vue区分不同的元素,从而提高性能  -->
      <li :key='item.id' v-for='(item, index) in myFruits'>
        <span>{{item.ename}}</span>
        <span>-----</span>
        <span>{{item.cname}}</span>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      循环结构-遍历数组
    */
    var vm = new Vue({
      el: '#app',
      data: {
        fruits: ['apple', 'orange', 'banana'],
        myFruits: [{
          id: 1,
          ename: 'apple',
          cname: '苹果'
        },{
          id: 2,
          ename: 'orange',
          cname: '橘子'
        },{
          id: 3,
          ename: 'banana',
          cname: '香蕉'
        }]
      }
    });
  </script>
</body>
</html>

打印结果如下:

② v-for遍历对象

语法:

<div v-for='(value, key, index) in object'></div>
/*
  循环结构-遍历对象
  v 代表对象的 value
  k 代表对象的 key
  i 代表 index
*/
<div v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>

<script>
 new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ],
    obj: {
        uname: 'zhangsan',
        age: 13,
        gender: 'female'
    }
  }
})
</script>

③ :key 的作用

  • :key用来给每个节点做一个唯一标识,主要是为了高效的更新虚拟DOM
<ul>
  // :key的作用:帮助Vue区分不同的元素,从而提高性能
  <li v-for="item in items" :key="item.id">...</li>
</ul>

④ v-if 和 v-for同时使用

  • 永远不要在同一个元素上同时使用 v-if 和 v-for,建议使用计算属性替代
  • 当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里面的变量
<div v-if='value==12' v-for='(value, key, index) in object'></div>

8 - 案例:Tab选项卡

  1. 实现静态UI效果
    用传统的方式实现标签结构和样式
  2. 基于数据重构UI效果
    将静态的结构和样式重构为基于Vue模板语法的形式
    处理事件绑定和js控制逻辑
  3. 声明式编程
    模板的结构和最终显示的效果基本一致
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .tab ul {
      overflow: hidden;
      padding: 0;
      margin: 0;
    }
    .tab ul li {
      box-sizing: border-box;
      padding: 0;
      float: left;
      width: 100px;
      height: 45px;
      line-height: 45px;
      list-style: none;
      text-align: center;
      border-top: 1px solid blue;
      border-right: 1px solid blue;
      cursor
    }
    .tab ul li:first-child {
      border-left: 1px solid blue;
    }
    .tab ul li.active {
      background-color: orange;
    }
    .tab div {
      width: 500px;
      height: 300px;
      display: none;
      text-align: center;
      font-size: 30px;
      line-height: 300px;
      border: 1px solid blue;
      border-top: 0px;
    }
    .tab div.current {
      display: block;
    }
  </style>
</head>
<body>
  // Vue模板
  <div id="app">
    <div class="tab">
      <ul>
        // 上面的li
        // change(index)里面的索引实际上就是 v-for='(item,index) in list 里面的index
        <li v-for='(item,index) in list' :key='item.id' v-on:click='change(index)' :class='currentIndex==index?"active":""'>{{item.title}}</li>
      </ul>
      // 下面的div
      <div v-for='(item, index) in list' :key='item.id' :class='currentIndex==index?"current":""'>
        <img :src="item.path">
      </div>
    </div>
  </div>

  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
  
    var vm = new Vue({
      el: '#app',
      data: {
        currentIndex: 0, // 选项卡当前的索引
        list: [{
          id: 1,
          title: 'apple',
          path: 'img/apple.png'
        },{
          id: 2,
          title: 'orange',
          path: 'img/orange.png'
        },{
          id: 3,
          title: 'lemon',
          path: 'img/lemon.png'
        }]
      },
      methods: {
        change: function(index){
          // 在这里实现选项卡切换操作:本质就是操作类名
          // 如何操作类名?就是通过currentIndex,currentIndex改变了,类名也会改变
          this.currentIndex = index;
        }
      }
    });
  </script>
</body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容