为了账号安全,请及时绑定邮箱和手机立即绑定

Vue.js 2.0 教程精华梳理(一) 基础

2016.11.10 17:33 35464浏览
Vue.js
第一部分 Vue.js 介绍

Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。Vue没有完全遵循MVVM格式,但Vue的设计无疑受到了它的启发。

1.1 浏览器限制

Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能模拟的 ECMAScript 5 特性(Object.defineProperty)。 Vue.js 支持所有兼容 ECMAScript 5 的浏览器。

1.2 开发版本与生产版本

  1. 开发版本——包含完整的警告和调试模式
  2. 生产版本——删除了警告,23.55kb min+gzip

1.3 引入vue.js

当前vue.js版本2.0

<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/vue/dist/vue.js">
第二部分 Vue.js基础

2.1 hello world

<div id="app">
    {{ message }}
</div>

var app = new Vue({
    el: '#app',
    data: {
         message: 'Hello Vue!'
    }
})

浏览器渲染结果:

Hello Vue!

Vue使数据和 DOM 被绑定在一起,所有的元素都是响应式的。当app.message改变时,会引起DOM的重新渲染。

2.2 Vue实例

2.2.1 选项对象

<div id='app'></div>

var vm = new Vue({
// 选项对象
})

在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。

选项对象包含常用的属性包括,在下文还会进行拓展:

var vm = {
    el:'',  // 以CSS选择器的形式选择根元素
    data:{
        message:'Hello Vue!'
    }, // 数据对象
    methods:{
        sayHello:function () {
            alert(this.message)
        }
    }, //方法对象,注意可数复数后面加s
  ... ...
}

2.2.2 代理data

Vue实例,即vm会代理选项对象中data对象里的所有属性,已上面创建的实例为例:

vm.message // =>Hello Vue!

在选项对象里,this表示构造器的实例,所以在methods对象中的方法也使用this.属性获取data里的属性:

……
methods:{
        sayHello:function () {
            alert(this.message) // =>Hello Vue!
        }
},
…… 

更常见的是data是一个外部的变量

var userInfo = {name:'Kyle Hu',age:20}
……
data: userInfo
…… 

此时data和userInfo是双向绑定的,二者有一方改变,对方都会改变。注意,userInfo一直存在在内存中。

就像你在写node程序时不能使用exports = function () {}导出模块一样,你不能像下面这样试图改变选项对象所绑定的data变量,因为这样完全破坏了data与vm的引用关系

<div>{{age}}</div>  

var userInfo = {name:'Kyle Hu',age:20}
……
data: userInfo
…… 

userInfo.age = 15; // DOM渲染成15
vm.age = 16; // DOM渲染成16
userInfo = {name:'Kyle Hu',age:22}; // 引用关系被破坏,DOM不会重新渲染
userInfo.age = 25; // 引用关系被破坏,DOM不会重新渲染
vm.age = 23; // DOM被渲染成23

2.2.3 实例属性与方法

既然vm.属性代理的是vm选项对象中的data对象中的属性,那么,我们想要访问诸如el,data等直接定义在选项对象里的属性怎么办呢?

Vue暴露了一些实例属性。如要访问诸如el,data这样的选项对象属性,则需在前面加上$,例如:

vm.$el // =>HTMLXXXDOM
vm.$data // => {message:'Hello Vue!'}

Vue还暴露了一些实例方法(不是methods里的方法),与实例属性相同,前面也加上$。比如监控元素改变的$watch方法

vm.$watch('a', function (newVal, oldVal) {
    // 这个回调将在 `vm.a`  改变后调用
})

2.2.4 实例的声明周期

2.3 模板语法

Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时, Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染(render)函数,使用可选的 JSX 语法。

2.3.1 插值

(1) 文本,使用 “Mustache” 语法(双大括号语法)

<div>{{message}}</div>

(2)不随vm.data变化的文本

<div v-once>{{message}}</div>

(3)纯HTML,注意防止XSS攻击

<div v-html="HTMLElement"></div>

(4)属性

<button v-bind:id="btn_id"  v-bind:disabled="check">click me</button>

如果check的值是false,则disabled属性将不会被渲染。以v-开头的是Vue.js的指令,你马上就能看到如何使用它们。

*>>注意:Vue.js1.x版本中的`{{{}}}、{{}}`等语法已被Vue.js 2.x淘汰**

2.3.2 表达式

可以在指令及{{}}中使用表达式,事实上,常量或变量的名称就是最简单的表达式。Vue可以通过是否带引号来判断一个表达式是一个变量还是一个常量字符串。所以在以后的内容里,指令及{{}}中的内容会被成为表达式。

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>

上面的表达式都被支持。{{}}和指令中只支持一个表达式,不支持语句。如果想要使用语句,可以使用一会儿要讲到的过滤器以及计算属性。

注板表达式中试图访问用户定义的全局变量。意:模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图使用用户自定义的全局变量

2.3.3 过滤器

Vue.js过滤器被用作一些常见的文本格式化。过滤器应该被添加在 mustache 插值的尾部,由“管道符”指示:

{{message|capitalize}}

上面的例子使用了Vue.js内置的顾虑器,作用是使message的值首字母大写。Vue.js也允许你自定义过滤器:

new Vue({
  // ...
  filters: {
    becomeHappy: function (value) {
      return 'I am happy to say:'  + value
    }
  }
})

过滤器可以串联,也可以接受参数。在接受参数时,第一个参数默认是前面返回的字符串,第二个参数开始是用户传递的参数,注意如果参数是字符串要加引号。

{{message | filterA | filterB('string', somevar)}}

2.3.4 指令

指令(Directives)是带有 v- 前缀的特殊属性。指令属性的值预期是单一 JavaScript 表达式(除了 v-for)。指令的职责就是当其表达式的值改变时相应地将某些行为应用到 DOM 上。指令能够实现条件渲染,列表渲染,绑定属性等诸多功能。

下面是一个使用指令例子:

<div id='app'><span v-if="condition" v-html="message"></span></div>

var vm = {
    el:'#app',
    data:{
        condition: true,
        message: '<span style="color:red">Hello Vue!</span>'
    }
}

浏览器显示:

<span style="color:red">Hello Vue!</span>

v-if指令会根据vm.condition判断是否渲染span,v-html指令会将message的内容以HTML的形式进行渲染。

有些指令接受一个“参数”,在指令后以冒号指出

<button v-bind:id="myBtn_id" v-on:click="sayHello"></button>

v-on用于指定事件,而v-bind用于绑定属性,由于它们非常常见,所以Vue.js为它们提供看缩写的形式:

<button :id="myBtn_id" @click="sayHello"></button>

sayHello为事件触发的函数,函数写在选项对象的methods属性中。

修饰符(Modifiers)是以半角句号 . 指明的特殊后缀,置于指令参数的后面,=(如果存在)前面。用于指出一个指定应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用

<form v-on:submit.prevent="onSubmit"></form>

<input v-model.trim="msg">
2.4 计算指令

在模板中表达式不宜过于复杂,可以使用计算指令讲逻辑抽离出来。

2.4.1 基础例子:

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
})

渲染结果:

Original message: "Hello"

Computed reversed message: "olleH"。

计算属性在选项对象的computed对象中编写。该对象的属性名即为需要计算得到的属性名,值为一个匿名函数。但这并不意味着把这个匿名函数的值赋给该属性(上例中的reversedMessage),事实上,在渲染的时候,该匿名函数会被执行,然后将return的值赋给computed对象的属性。

2.4.2 计算setter

以上例中,reversedMessage依赖于vm.message属性,并随之变化。相当于我们为之创建了一个getter。
然而如果我们希望reversedMessage改变也会引起message的改变,则需要再为之创建一个setter:

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

现在在运行 vm.fullName = 'John Doe' 时, setter 会被调用, vm.firstName 和 vm.lastName 也会被对应更新。

2.4.3 计算缓存 vs Methods

<div>{{getFullName()}}</div>

你可能已经注意到我们可以通过调用表达式中的method来达到同样的效果,与计算属性的区别在于计算属性是基于它的依赖缓存的。只有当其依赖的数据发生变化时才会重新计算取值。相比而言,每当重新渲染时,method调用总会执行函数。

所以制作计时器的计划会因此失败

computed: {
    now:function () {
        return new Date()
    }
}

2.4.5 计算属性 vs watcher

Vue.js提供了$watch,当制定数据变化是其中的相关函数会被调用,也可以起到计算属性的效果。

 watch: {
    // 如果 question 发生改变,这个函数就会运行
    question: function (newQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },

二者区别在于计算属性将会在依赖的数据改变后立即发生变化,而watcher更适合处理异步的情况,直到我们得到最终结果时,才设置中间状态。

2.5 style与class

class和style都是属性,可以使用v-bind指令进行绑定,Vue.js加强了它们。表达式的结果除了可以是字符串外,还可以是数组或对象。

2.5.1 class

v-bind指令不影响原有的class。

(1)对象语法

<div :class="{active:condition}"></div>

active是一个class的名称,而condition则是一个表达式,当condition为true的时候,class将被执行渲染。

你也可以直接传一个表达式:

<div v-bind:class="classObject"></div>

... 
data: {
  classObject: {
    active: true,
    'text-danger': false
  }
}
...

(2)数组语法

<div v-bind:class="[activeClass, errorClass]">

data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

与对象语法不同,数组语法中元素全部为表达式。你也可以将表达式设置为对象

<div v-bind:class="[{ active: isActive }, errorClass]">

2.5.2 style

这里css属性名支持中划线命名法及驼峰命名法。

(1)对象语法

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

data: {
  activeColor: 'red',
  fontSize: 30
}

对象的属性是css属性名,值是表达式的返回值。当然推荐你把表达式对象抽离出来

(2)数组语法

v-bind:style 的数组语法可以将多个样式对象应用到一个元素上,每个元素都是一个返回CSS对象的表达式。

<div v-bind:style="[baseStyles, overridingStyles]">

(3)自动添加前缀

当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。

2.6 条件渲染

2.6.1 v-if/v-else

vue.js把v-if指令的功能抽离出来,只用来判断DOM元素是否进行渲染。

<h1 v-if="ok">Yes</h1>

v-if指令不能作用于根元素,否则会给出警告并报错。

可以使用v-else指令设置不满足条件的话将做什么,v-else必须紧跟v-if(或者后面提到的v-show),否则无法被识别。

<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>

v-if是惰性的,在第一次条件为真的时候才进行渲染。

2.6.2 template

子元素还好应付,如果有若干个同级元素需要根据条件进行判断是否渲染,则需要使用template

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

template本身不会被渲染成DOM节点。

2.6.3 v-show

v-show是在会被渲染成DOM,若其后表达式的值为假,则会在渲染时加上style="display:none"。由于其总是会被渲染,所以v-show可以被绑定到根结点上。同时,Vue.js规定v-show不能作用于template。显然,v-show更适合频繁切换的情况。

  <p v-show="okay">okay</p>
  <p v-show="!okay">not okay</p>
2.7 列表渲染

2.7.1 迭代数组

最基本的渲染形式是对数组的处理:

<ul>
    <li v-for="student in students">{{student.name}}</li>
</ul>

students: [{name: 'Jack', age: 15},
         {name: 'Tom', age: 15},
         {name: 'LiMing', age: 15}]

2.7.2 迭代对象

<ul>
    <li v-for="value in person">{{value}}</li>
</ul>

... ...
data: {
    person:{
        name:"Jack",
        age:17
    }
}

2.7.3 数据访问权限

在 v-for 块中,我们拥有对父作用域及当前作用域属性的完全访问权限。

<ul>
    <li v-for="person in persons">
        {{person.name}}
        <span v-html="person.html"></span>
    </li>
</ul>

2.7.4 template

如同 v-if 模板,你也可以用带有 v-for 的 <template> 标签来渲染多个同级元素块。

2.7.5 key(键名)与index

你可以提供索引和键名作为参数

<div v-for="(value[ ,key[,index]]) in object">{{index}}.{{value}}</div>

$Index和$key在Vue.js2.0中已经被淘汰

2.7.6 迭代整数

此外,v-for还可以迭代整数

<div>
  <span v-for="n in 10">{{ n }}</span>
</div>

输出1至10

2.7.8 使用key帮Vue一个小忙

重新渲染一个单独的值,比如message对Vue来说是小菜一碟。但如果当列表里的某一个值被改变,需要重新渲染整个列表则是不可接受的。

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,而不是移动 DOM 元素来匹配数据项的顺序, Vue 将简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

我们为列表中每个元素提供一个key以帮助Vue.js跟踪每个节点的身份,从而重用和重新排序现有元素。

<div v-for="student in students" :key="student.student_id">
  <!-- 内容 -->
</div>

data: { 
    students: [{student_id:100100,name:'Jack'}, {student_id:'100102', name: 'Tom'}]
}

2.7.9 数组重新渲染

Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

你打开控制台,然后用前面例子的 items 数组调用突变方法:

example1.items.push({ message: 'Baz' }) 

对于诸如filter(), concat(), slice()等非变异方法,替换掉整个数组即可。Vue 实现了一些智能启发式方法来最大化 DOM 元素重用,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

不过换个思路,如果我不希望真正改变数组的顺序或者值,可以使用计算属性或Methods实现

2.7.9 数组渲染时的缺陷与解决办法

由于 JavaScript 的限制, Vue 不能检测以下变动的数组:

  1. 当你直接设置一个项的索引时,例如: vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如: vm.items.length = newLength

Vue也提供了解决问题的办法,解决第一个问题:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)

// Array.prototype.splice`
example1.items.splice(indexOfItem, 1, newValue)

解决第二个问题:

example1.items.splice(newLength)
2.8 事件监听器

2.8.1 内联监听器

可以为事件监听器传递参数,如果需要传递事件event对象,则写成$event的形式

<button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>

...
methods:{warn:function (message, event) {... ...}} 
...

2.8.2 在HTML上绑定事件?!

你可能注意到这种事件监听的方式违背了关注点分离(separation of concern)传统理念。不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:

  1. 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。

  2. 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。

  3. 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。

2.8.3 事件修饰符

Vue提供的事件修饰符将常见的事件设置(比如阻止元素默认事件,或阻止事件冒泡)旨在让我们的Methods更加关注数据逻辑。通过由点(.)表示的指令后缀来调用修饰符。

<a v-on:click.stop="doThis"></a>

常见的事件修修饰符有以下几个:

  1. .stop // 阻止事件冒泡
  2. .prevent // 阻止元素默认事件
  3. .capture // 使用事件捕获模式监听事件
  4. .self //只当事件在该元素本身(而不是子元素)触发时触发回调

事件修饰符可以串联使用:

<a v-on:click.stop.prevent="doThat"></a>

2.8.4 按键修饰符

修饰符中还有一种按键修饰符,其值是键盘按键的keycode或者预先定义好的keycode别名,例如:

<input v-on:keyup.13="submit">
<input v-on:keyup.enter = "submit">

当按下回车键时,执行submit。

下面是全部的按键别名:

  1. enter
  2. tab
  3. delete (捕获 “删除” 和 “退格” 键)
  4. esc
  5. space
  6. up
  7. down
  8. left
  9. right

我们也可以为按键自定义别名:

// 此时我们就可以通过使用@keyup.f1代替@keyup.112了
Vue.config.keyCodes.f1 = 112
2.9 表单控件绑定

你可以用 v-model 指令在表单控件元素上创建双向数据绑定,但其本质上不过是语法糖。

最基本的例子:

<TextArea v-model="message" placeholder="edit me">
点击查看更多内容
98人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 邀请有奖 帮助中心 APP下载
官方微信

举报

0/150
提交
取消