1

插值语法(Mustache)

Mustache

数据是响应式的。

<div id="app">
  <p>{{message}}</p>
  <p>{{counter*2}}</p> /*也可以是一个表达式*/
</div>
<script src="../js/vue.js"></script>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      counter: 2
    },
  })
</script>

v-once

数据不是响应式的

<div id="app">
  <p v-once>{{message}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello vue"
    },
  })
</script>

当在控制台 app.message = 'hello' 时,页面中的数据不会发生改变。

v-html

该指令后面往往会跟上一个string类型,会将string的html解析出来并且进行渲染。
v-html.png

v-text

v-text作用和Mustache比较相似:都是用于将数据显示在界面中。会覆盖标签中的内容。

<div id="app">
  <p v-text="message">hello world</p>
  <p>{{message}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
    },
  })
</script>

v-pre

v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。

<div id="app">
  <p v-pre>{{message}}</p>
  <p>{{message}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
    },
  })
</script>
//{{message}}
//hello vue

v-block

在某些情况下,我们浏览器可能会直接显然出未编译的Mustache标签。当Mustache标签未编译完成时,v-cloak显示,当编译完成时v-clock消失。若要当Mustache标签未编译完成时,不显示,则写一个css代码。

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>
<div id="app" v-cloak>
  {{message}}
</div>
<script src="../js/vue.js"></script>
<script>
  setTimeout(() => {
    const app = new Vue({
      el: "#app",
      data: {
        message: "hello vue"
      },
      methods: {}
    })
  }, 5000);
</script>
</body>

绑定属性

v-bind基础

除了内容需要动态来决定外,某些属性我们也希望动态来绑定。这个时候,我们可以使用v-bind指令:缩写::。v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值。比如图片的链接src、网站的链接href、动态绑定一些类、样式等等

<div id="app">
  {{message}}
  <img :src="imgUrl" alt="">
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      imgUrl: "https://www.baidu.com/img/bd_logo1.png?where=super",
    },
    methods: {}
  })
</script>

绑定class

绑定class有两种方式:对象语法、数组语法。

对象语法:class后面跟的是一个对象。

用法一:直接通过{}绑定一个类

<p :class="{active1:isActive1,active2:isActive2}">class对象</p>

data: {
  isActive1: true,
  isActive2: false
}

<style>
    .active1 {
      color: #9889c1;
    }

    .active2 {
      font-size: 30px;
    }
</style>

用法二:也可以通过判断,传入多个值

<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>

用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类

<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>

用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性

<h2 class="title" :class="classes">Hello World</h2>

data: {
  isActive1: true,
  isActive2: false
},
computed: {
  getClass() {
    return {active1: this.isActive1, active2: this.isActive2};
  }
}
数组语法:class后面跟的是一个数组。

用法一:直接通过{}绑定一个类

<h2 :class="['active']">Hello World</h2>

用法二:也可以传入多个值

<h2 :class=“[‘active’, 'line']">Hello World</h2>

用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类

<h2 class="title" :class=“[‘active’, 'line']">Hello World</h2>

用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性

<h2 class="title" :class="classes">Hello World</h2>

绑定style

可以利用v-bind:style来绑定一些CSS内联样式。在写CSS属性名的时候,比如font-size
我们可以使用驼峰式 (camelCase) fontSize或短横线分隔 (kebab-case,记得用单引号括起来) 'font-size'
绑定class有两种方式:对象语法、数组语法

对象语法
<h2 :style="{color:style1,fontSize:style2+'px'}">style对象</h2>

<script>
  const app = new Vue({
    el: "#app",
    data: {
      style1: "red",
      style2: 40
    }
  })
</script>

style后面跟的是一个对象类型:
对象的key是CSS属性名称。
对象的value是具体赋的值,值可以来自于data中的属性。

数组语法
<div id="app">
  <h2 :style="[color,fontSize]">style数组</h2>
</div>

<script>
  const app = new Vue({
    el: "#app",
    data: {
      color: {
        color: "red"
      },
      fontSize: {
        fontSize: '40px',
      }
    }
  })
</script>

style后面跟的是一个数组类型,多个值以,分割即可。

计算属性

在模板中可以直接通过插值语法显示一些data中的数据。但在某些情况,需要对数据进行一些转化后再显示,或需要将多个数据结合起来进行显示。比如有firstNamelastName两个变量,需要显示完整的名称。但如果多个地方都需要显示完整的名称,就需要写多个{{firstName}} {{lastName}}我们可以将上面的代码换成计算属性:计算属性是写在实例的computed选项中的。

  • 使用计算属性时是不需要加()的。
  • 计算属性中可以进行一些复杂的操作。如数组的高阶函数。
<div id="app">
  <p>
    {{fullName}}
  </p>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      firstName: "pillar",
      lastName: "liang"
    },
    methods: {},
    computed: {
      fullName: function () {
        return this.firstName + " " + this.lastName;
      }
    },
  })
</script>

计算属性的setter和getter

每个计算属性都包含一个getter和一个setter。在上面的例子中,我们只是使用getter来读取。
在某些情况下,你也可以提供一个setter方法(不常用)。

  • 一般只使用get方法,此时属性为只读属性。
  • 使用计算属性的时候不能加(),它默认会调用get()方法

在需要写setter的时候,代码如下:

<div id="app">
  {{message}}
  <p>{{fullName}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      firstName: "zhang",
      lastName: "san",
    },
    methods: {},
    computed: {
      fullName: {
        set: function (newValue) {
          let names = newValue.split(" ");
          this.firstName = names[0];
          this.lastName = names[1];
        },
        get: function () {
          return this.firstName + " " + this.lastName;
        }
      }
    }
  })
</script>

计算属性的缓存

计算属性会进行缓存,如果多次使用且计算属性中的数据未发生变化时,计算属性只会调用一次。

<div id="app">
  <p>{{getFullName()}}</p>
  <p>{{getFullName()}}</p>
  <!--  输出两个“methods调用”-->

  <p>{{fullName}}</p>
  <p>{{fullName}}</p>
  <!--  输出一个“computed调用”-->
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      firstName: "zhang",
      lastName: "san"
    },
    methods: {
      getFullName: function () {
        console.log("methods调用");
        return this.firstName + " " + this.lastName;
      }
    },
    computed: {
      fullName: function () {
        console.log("computed调用");
        return this.firstName + " " + this.lastName;
      }
    }
  })
</script>

事件监听

v-on基础

在前端开发中,我们需要经常和用于交互。这个时候,就必须监听用户发生的事件,如点击、拖拽、键盘事件等等。在Vue中监听事件使用v-on指令。缩写:@

<div id="app">
  <p>{{count}}</p>
  {{test()}}
  <button @click="add">+</button>/*这里的add可以省略掉()*/
  <button @click="{{count++}}">点击</button>
  <button @click="tdelete">-</button>/*这里的tdelete可以省略掉()*/
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      count: 0,
    },
    methods: {
      test() {
        return "这是测试"
      },
      add() {
        this.count++;
      },
      tdelete() {
        this.count--;
      }
    }
  })
</script>

v-on 参数

当通过methods中定义方法,以供@click调用时,需要注意参数问题:

  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去。
<div id="app">
  {{message}}
  <!--  情形一:事件调用的方法没有参数,调用时可以省略() -->
  <button @click="btn1Click">1</button>
  <!--  情形二:事件调用的方法有参数,调用时省略(),将事件event传进去-->
  <button @click="btn2Click">3</button>
  <!--  情形三:事件调用的方法既有参数又有event对象-->
  <button @click="btn3Click('a',$event)">4</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue"
    },
    methods: {
      btn1Click() {
        console.log("方法没有参数");
      },
      btn2Click(a) {
        console.log("---" + a);
      },
      btn3Click(a, event) {
        console.log("---" + a, event);
      }
    }
  })
</script>

v-on修饰符

Vue提供了修饰符来帮助我们方便的处理一些事件:

修饰符 描述
.stop 调用 event.stopPropagation()
.prevent 调用 event.preventDefault()
.{keyCode \ keyAlias} 只当事件是从特定键触发时才触发回调
.native 监听组件根元素的原生事件
.once 只触发一次回调
<div id="app">
  {{message}}
  <!--  1. 停止冒泡-->
  <p @click="divClick">
    <button @click.stop="btnClick()">1</button>
  </p>
  <!--  2. 阻止默认事件-->
  <form action="baidu">
    <input type="submit" @click.prevent="submitClick">
  </form>
  <!--  3.键修饰符-->
  <p>
    <input type="text" @keyup="keyClick">
    <input type="text" @keyup.enter="keyClick">
    <input type="text" @keyup.13="keyClick">
  </p>
  <!--  v-once-->
  <p>
    <button @click.once="onceClick">once</button>
  </p>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue"
    },
    methods: {
      divClick() {
        console.log("divClick");
      },
      btnClick() {
        console.log("btnClick");
      },
      submitClick() {
        console.log("submitClick");
      },
      keyClick() {
        console.log("keyClick");
      },
      onceClick() {
        console.log("onceClick");
      }
    }
  })
</script>

条件判断

条件渲染

v-ifv-else-ifv-else 这三个指令与JavaScript的条件语句ifelseelse if类似。Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件。

<div id="app">
  {{message}}
  <p v-if="score>=90">优秀</p>
  <p v-else-if="score<90&&score>=60">及格</p>
  <p v-else="score<60">不及格</p>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      score: 90
    },
    methods: {}
  })
</script>

v-show指令

v-show的用法和v-if非常相似,也用于决定一个元素是否渲染

<div id="app">
  {{message}}
  <div v-show="isShow">
    <p>haha</p>
    <p>xixi</p>
  </div>
  {{message}}
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      isShow: true,
    },
    methods: {}
  })
</script>

v-if和v-show对比

v-ifv-show都可以决定一个元素是否渲染。v-if当条件为false时,压根不会有对应的元素在DOM中。v-show当条件为false时,仅仅是将元素的display属性设置为none而已。
当需要在显示与隐藏之间切片很频繁时,使用v-show。当只有一次切换时,通过使用v-if

条件渲染案例

要求:用户在登录时,可以切换使用用户账号登录还是邮箱地址登录。
小问题:如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。但是按道理讲,我们应该切换到另外一个input元素中了。在另一个input元素中,我们并没有输入内容。为什么会出现这个问题呢?
问题解答:这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。
问题.png

<div id="app">
  <p v-if="isUser">
    <label for="user">用户账号</label>
    <input type="text" id="user" placeholder="用户账号" key="user">
  </p>
  <p v-else>
    <label for="email">用户邮箱</label>
    <input type="email" id="email" placeholder="用户邮箱" key="email">
  </p>
  <button @click="isUser = !isUser">切换类型</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      isUser: true
    },
    methods: {}
  })
</script>

循环遍历

v-for遍历数组

当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。v-for的语法类似于JavaScript中的for循环。格式如下:item in items的形式。
在遍历的过程中,拿到元素在数组中的索引值:语法格式:v-for=(item, index) in items。其中的index就代表了取出的item在原数组的索引值。

<div id="app">
  {{message}}
  <!-- 1. 没有使用索引值 -->
  <ul>
    <li v-for="item in color">{{item}}</li>
  </ul>
  <!-- 2. 获取索引值-->
  <ul>
    <li v-for="(item,index) in color">
      {{index+1}}--{{item}}
    </li>
  </ul>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      color: ["red", "black", "yellow"],
    },
    methods: {}
  })
</script>

v-for遍历对象

<div id="app">
  <!--  3.-->
  <ul>
    <li v-for="(item,key) in info">
      {{key}}:{{item}}
    </li>
  </ul>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      info: {
        name: "pillar",
        sport: "swim"
      }
    },
    methods: {}
  })
</script>

组件的key属性

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。

为什么需要这个key属性呢?
这个其实和Vue的虚拟DOM的Diff算法有关系。借用React’s diff algorithm中的一张图来简单说明一下:
key.png
当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点。我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?所以我们需要使用key来给每个节点做一个唯一标识。Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。Diff算法会看之前的key对应的value有没有改变,再去执行新值的插入等操作。当数据发生变化时,会重新渲染虚拟DOM,在虚拟DOM中执行Diff算法,在反映到真实DOM中。所以一句话,key的作用主要是为了高效的更新虚拟DOM。

数组中哪些方法是响应式的?

实际上就是可以改变数组自身的方法,但是通过索引修改数组元素虽然能原数组发生了改变,但是无法实现响应式更新。

<div id="app">
  {{message}}
  <ul>
    <li v-for="item in letters">{{item}}</li>
  </ul>
  <button @click="btnClick">click</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      letters: ["A", "B", "C", "D"]
    },
    methods: {
      btnClick() {
        // this.letters.push("F");
        this.letters[0] = "ad";
        console.log(this.letters);
      }
    }
  })
</script>

v-model

Vue中使用v-model指令来实现表单元素和数据的双向绑定。

v-model原理

v-model其实是一个语法糖,它的背后本质上是包含两个操作:
1.v-bind绑定一个value属性
2.v-on指令给当前元素绑定input事件
也就是说下面的代码:等同于下面的代码:

<input type="text" v-model="message">
//等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
<div id="app">
  <input type="text" v-model="message">
  <input type="text" :value="message" @input="message = $event.target.value">
  <input type="text" :value="message" @input="valueChange($event.target.value)">

</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue"
    },
    methods: {
      valueChange(value) {
        this.message = value;
      }
    }
  })
</script>

v-model:radio

如果没有v-model,必须加name属性,加上v-model,name属性可以省略。

<div id="app">
  <label for="male">
    <input type="radio" id="male" name="sex" value="男" v-model="sex">男
  </label>
  <label for="female">
    <input type="radio" id="female" name="sex" value="女" v-model="sex">女
  </label>
  <h2>{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      sex: "女",
    },
    methods: {}
  })
</script>

v-model:checkbox

复选框分为两种情况:单个勾选框和多个勾选框。
单个勾选框:v-model即为布尔值。此时input的value并不影响v-model的值。
多个复选框
当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
当选中某一个时,就会将input的value添加到数组中。

<div id="app">
  <!--  单选框-->
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">同意协议
  </label>
  <button :disabled="!isAgree">下一步</button>
  <!--  多选框-->
  <label for="red">
    <input type="checkbox" value="red" id="red" v-model='color'>红色
  </label>
  <label for="black">
    <input type="checkbox" value="black" id="black" v-model="color">黑色
  </label>
  <label for="yellow">
    <input type="checkbox" value="yellow" id="yellow" v-model="color">黄色
  </label>
  <h2>{{color}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      isAgree: false,
      color: []
    },
    methods: {}
  })
</script>

v-model:select

和checkbox一样,select也分单选和多选两种情况。
单选:只能选中一个值。v-model绑定的是一个值。当我们选中option中的一个时,会将它对应的value赋值到v-model指定的字符串中。
多选:可以选中多个值。v-model绑定的是一个数组。当选中多个值时,就会将选中的option对应的value添加到v-model指定的数组中。

<div id="app">
  <!--  <select name="color" id="color" v-model="fruit" multiple>-->
  <!--    <option value="red">红色</option>-->
  <!--    <option value="black">黑色</option>-->
  <!--    <option value="yellow">黄色</option>-->
  <!--  </select>-->
  <!--  <h2>{{fruit}}</h2>-->
  <label v-for="item in color" :for="item">
    <input type="checkbox" :value="item" :id="item" v-model="colors">{{item}}
  </label>
  <h2>{{colors}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: "#app",
    data: {
      message: "hello vue",
      fruit: '',
      color: ["red", "black", "green"],
      colors: []
    },
    methods: {}
  })
</script>

值绑定

就是v-bind在input中的应用,即动态的给value赋值。前面的value中的值,可以回头去看一下,都是在定义input的时候直接给定的。但是真实开发中,这些input的值可能是从网络获取或定义在data中的。所以我们可以通过v-bind:value动态的给value绑定值。

修饰符

lazy修饰符:

默认情况下,v-model默认是在input事件中同步输入框的数据的。也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
lazy修饰符可以让数据在失去焦点或者回车时才会更新。

number修饰符:

默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
number修饰符可以让在输入框中输入的内容自动转成数字类型。

trim修饰符:

如果输入的内容首尾有很多空格,通常我们希望将其去除。trim修饰符可以过滤内容左右两边的空格。

<div id="app">
  <label>
    <input type="text" v-model.lazy="message">
  </label>
  <label for="num">
    <input type="text" id="num" v-model.number="num">
  </label>
  <h2>{{typeof num}}</h2>
  <label for="in">
    <input type="text" id="in" v-model.trim="lets">
  </label>
  <h2>{{lets}}</h2>
</div>

梁柱
135 声望12 粉丝

« 上一篇
1.vue简介
下一篇 »
3.Vue组件开发