2.Vue 介绍

2019-05-08  本文已影响0人  璎珞纨澜

一、 Vue 介绍

通过下面这个姓名展示的案例我们先来对比下操作 DOM 的繁琐 与使用 Vue 的简便:

  1. 通过操作 DOM 元素实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app">
        姓氏:<input type="text" id="surname" value="黄">
        <br>
        名字:<input type="text" id="givenname" value="慧">
        <br>
        <p id="fullname">黄慧</p>
    </div>
    <script>
        var surname = document.getElementById('surname')
        var givenname = document.getElementById('givenname')
        var fullname = document.getElementById('fullname')

        surname.addEventListener('input', handleTextInput)
        givenname.addEventListener('input', handleTextInput)

        function handleTextInput() {
            fullname.innerHTML = surname.value + givenname.value
            console.log(fullname.innerHTML)
        }
    </script>
</body>
</html>
  1. 使用 Vue
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app">
        姓氏:<input type="text" v-model="surname">
        <br>
        名字:<input type="text" v-model="givenname">
        <br>
        <p>{{ surname + givenname }}</p>
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el:'#app',
            data:{
                surname:'黄',
                givenname:'慧'
            }
        })
    </script>
</body>
</html>

二、 Vue 实例

Vue 实例的选项

每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue 实例开始的:

var vm = Vue({
  // 选项
})

当创建一个 Vue 实例时,你可以传入一个选项对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,可以在 API 文档 中浏览完整的选项列表。

1. el 选项:

参考文档:https://cn.vuejs.org/v2/api/#el

2. data 选项:

参考文档:https://cn.vuejs.org/v2/api/#data

3. methods 选项:

参考文档:https://cn.vuejs.org/v2/api/#methods

4. computed 选项:

用于定义计算属性,详细见 四、计算属性

Vue 实例的生命周期

什么是生命周期?
从 Vue 实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
生命周期钩子
生命周期钩子 = 生命周期函数 = 生命周期事件
有哪些生命周期函数?

lifecycle.png

三、 数据绑定

1. 文本插值

数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值,Mustache 标签将会被替代为对应数据对象上的 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新:<span>Message: {{ msg }}</span>

2. 一次性绑定

通过 v-once 指令,执行一次性插值,当数据改变时,插值处的内容不会更新。但会影响到该节点上的其它数据绑定:<span v-once>这个将不会改变: {{ msg }}</span><span>这个将不会改变: {{ *msg }}</span>

3. 输出 HTML
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

或者写成:

<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span>{{{ rawHtml }}}</span></p>

结果:


v-html
4. 属性绑定
5. 使用 JavaScript 表达式

Vue.js 数据绑定提供了完全的 JavaScript 表达式支持

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}

<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
6. 分隔符

Vue.js 数据绑定的语法被设计为可配置的。我们可以在 Vue.config 中配置绑定的语法。Vue.config 是一个对象,包含了 Vue.js 所有的全局配置,可以在 Vue 实例化前修改其中的属性。分隔符在 Vue.config 的源码定义如下:

<!--源码目录 src/config.js-->
let delimiters = ['{{','}}']
let unsafeDelimiters = ['{{{','}}}']

四、 指令

指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

1. 常用指令

详细指令参见https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4

条件渲染指令:
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>
<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

v-ifv-show 对比,用哪个?
1. v-if 支持 template 语法,v-show 不支持。
2. 在切换 v-if 模块时, Vue.js 有一个局部编译/卸载的过程,因为 v-if 中的模板可能包括数据绑定或子组件。v-if 是真实的条件渲染,因为它会确保条件块在切换时合适点的销毁和重建条件块内部的事件监听器和子组件。v-if 是惰性的,如果初始渲染条件为假,则什么也不做,在条件第一次变为真时才开始局部编译(编译会被缓存起来)。相比之下 v-show 简单的多,元素始终被编译并保留,只是简单的基于 CSS 切换。
3. v-if 有更高的切换消耗,而 v-show 有更高的初始渲染消耗。如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

列表渲染指令:v-for

详细参见 五、列表渲染

注册事件指令:v-on

详细参加 五、事件处理

属性绑定指令: v-bind
只渲染一次指令:v-once

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

绑定输出 HTML 指令:v-html
表单控件双向数据绑定指令:v-model

参考官网:https://cn.vuejs.org/v2/guide/forms.html

数据绑定指令:v-text
加快编译指令:v-pre

告诉 vue不要解析这个节点节内部的内容,浪费时间。跳过大量没有指令的节点会加快编译。例如含有大量的网页文本内容节点可以加这个指令。

2. 参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示,如:

<a v-bind:href="url">...</a>
<a v-on:click="doSomething">...</a>

3. 指令修饰符

修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():<form v-on:submit.prevent="onSubmit">...</form>

4. 指令缩写

Vue 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写:

<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>

五、列表渲染

v-for 指令的基本用法

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
结果
<ul id="v-for-object" class="demo">
  <li v-for="(value, name, index) in object">
    {{ index }}. {{ name }}: {{ value }}
  </li>
</ul>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})
结果
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

数组更新检测

变异方法(mutation method)

我们知道,JS Array 对象有以下变异方法(会改变调用了这些方法的原始数组),其 MDN 解释如下:

Vue.js 将被侦听数组的变异方法进行了包裹,所以在 v-for 循环数组进行列表渲染时候如果该数组调用了这些方法,会触发视图的重新渲染。可以打开控制台,然后对前面例子的 items 数组尝试调用变异方法。比如 app.items.push({ message: 'Baz' })

DEMO演示如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Vue-mutation method</title>
</head>
<body>
    <ul id="app">
      <li v-for="item in items">
        {{ item }}
      </li>
    </ul>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        var app = new Vue({
          el: '#app',
          data: {
            items: ['March', 'Jan', 'Feb', 'Dec']
          }
        })
    </script>
</body>
</html>
演示结果
替换数组

数组的非变异方法(non-mutating method)不会改变原始数组,而总是返回一个新数组,例如:

app.items = app.items.filter(function (item) {
  return item.message.match(/Foo/)
})

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

注意事项

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

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

为了解决问题 1,可以用以下两种方式实现相同的效果,同时也将在响应式系统内触发状态更新:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

为了解决问题 2,可以这样:

vm.items.splice(newLength)

另外,数组更新检测除了 Vue.set() (实例方法又名为vm.$set)方法,还有 Vue.delete (实例方法又名为 vm.$delete)方法,用于从目标数组中查找并删除元素。

// Vue.delete
Vue.delete(vm.items, indexOfItem)
// vm.$delete
vm.$delete(vm.items, indexOfItem)
// 也等价于
vm.items.splice(indexOfItem, 1)
演示结果

对象更新检测

注意事项

还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是可以使用Vue.set(object, propertyName, value) (或者 vm.$set(object, propertyName, value))方法向嵌套对象添加响应式属性。

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

Object.assign(vm.object, {
  favoriteColor: 'Vue Green'
})

因为表达式只会修改vm.userProfile,vm.userProfile仍然指向原引用地址(常用于 合并 对象)
应该这样做:

vm.object= Object.assign({}, vm.object, {
  favoriteColor: 'Vue Green'
})

因为 vm.userProfile 可能是父级组件传过来的prop,为了遵循单向数据流的设计理念,不直接修改该数据对象,而是生成一个新的数据对象。该表达式右侧会生成一个新的对象,vm.userProfile 会指向一个新的引用地址(常用于 浅拷贝 对象)

Demo :

    <ul id="v-for-object" class="demo">
      <li v-for="(value, name, index) in object">
        {{ index }}. {{ name }}: {{ value }}
      </li>
    </ul>
    <script>
        const vm = new Vue({
          data: {
            object: {
              title: 'How to do lists in Vue',
              author: 'Jane Doe',
              publishedAt: '2016-04-10'
            }
          }
        }).$mount('#v-for-object')
直接添加对象属性 通过vm.$set()添加对象属性 通过Object.assign()合并对象 通过Object.assign()浅拷贝对象
<div>
  <span v-for="n in 10">{{ n }} </span>
</div>
执行结果
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
<ul id="v-for-component" class="demo">
  <my-component
    v-for="(value, name, index) in object"
    :value="value"
    :name="name"
    :index="index"
    :key="index">   
  </my-component>
</ul>
<script>
  Vue.component('my-component',{
    props: ['value','name','index'],
    template: `
      <li>{{ index }}. {{ name }}: {{ value }}</li>         
    `
  })

  const vm = new Vue({
    data: {
      object: {
        title: 'How to do lists in Vue',
        author: 'Jane Doe',
        publishedAt: '2016-04-10'
      }
    }
  }).$mount('#v-for-component')

不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

注意,由于 <li> 只能出现在 <ul> 列表的内部,上述写法会导致我们使用这些有约束条件的元素时遇到一些问题潜在的浏览器解析错误,例如,组件的 template 中不含有 <li> 标签,则会解析报错。幸好特殊的 is 特性给了我们一个变通的办法。

<ul id="v-for-component" class="demo">
  <li is="my-component"
    v-for="(value, name, index) in object"
    :value="value"
    :name="name"
    :index="index"
    :key="index">   
  </li>
</ul>

六、事件处理

用 v-on 指令可以监听 DOM 事件,并在触发时运行一些 JavaScript 代码。很多事件事件处理逻辑会更为复杂,直接把 JavaScript 代码写在 v-on 指令中是不可行的,因此 v-on 还可以接收一个需要调用的方法名称,该方法定义在 methods 选项中。

v-on绑定方法的两种方式

事件修饰符

在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。Vue 提供了以下事件修饰符:

这些事件修饰符还可以串联,例如:<a v-on:click.stop.prevent="doThat"></a>

Demo演示:

var vm = new Vue({
  methods: {
    div1Handler() {
      console.log('这是触发了 inner div 的点击事件')
    },
    btnHandler() {
      console.log('这是触发了 btn 按钮 的点击事件')
    },
    linkClick() {
      console.log('触发了连接的点击事件')
    },
    div2Handler() {
      console.log('这是触发了 outer div 的点击事件')
    }
  }
}).$mount('#app')
  1. 单击事件冒泡
<div id="app">
  <div class="inner" @click="div1Handler">
    <input type="button" value="戳他" @click="btnHandler">
  </div>
</div>
单击事件冒泡
  1. 使用 .stop 阻止冒泡
<div id="app">
  <div class="inner" @click="div1Handler">
    <input type="button" value="戳他" @click.stop="btnHandler">
  </div>
</div>
使用 .stop 阻止冒泡
  1. 使用 .self 实现只有点击当前元素时候,才会触发事件处理函数
<div id="app">
  <div class="inner" @click.self="div1Handler">
    <input type="button" value="戳他" @click="btnHandler">
  </div>
</div>
使用 .self 实现只有点击当前元素时候,才会触发事件处理函数
  1. 演示: .stop 和 .self 的区别
<div id="app">
  <div class="outer" @click="div2Handler">
    <div class="inner" @click="div1Handler">
      <input type="button" value="戳他" @click.stop="btnHandler">
    </div>
  </div>
</div>
使用 .stop 能阻止当前元素的冒泡行为

.self 只会阻止自己身上冒泡行为的触发,并不会真正阻止 冒泡的行为:

<div id="app">
  <div class="outer" @click="div2Handler">
    <div class="inner" @click.self="div1Handler">
      <input type="button" value="戳他" @click="btnHandler">
    </div>
  </div>
</div>
使用 .self 实现只有点击当前元素时候,才会触发事件处理函数
  1. 使用 .capture 实现捕获触发事件的机制
<div id="app">
  <div class="inner" @click.capture="div1Handler">
    <input type="button" value="戳他" @click="btnHandler">
  </div>
</div>
使用 .capture 实现捕获触发事件的机制
  1. 单击触发事件默认行为
<div id="app">
  <a href="http://www.baidu.com" @click="linkClick">有问题,先去百度</a>
</div>
单击触发事件默认行为
  1. 使用 .prevent 阻止默认行为
<div id="app">
  <a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a>
</div>
使用 .prevent 阻止默认行为
  1. 使用 .once 只触发一次事件处理函数
<div id="app">
  <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>
</div>
使用 .once 只触发一次事件处理函数

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent只会阻止对元素自身的点击。

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 $event.key 是 Enter 时调用 vm.submit() -->
<input v-on:keyup.enter="submit">

<!-- 只有在 $event.key 等于 PageDown 时调用 vm.onPageDown() -->
<input v-on:keyup.page-down="onPageDown">

使用 keyCode 特性也是允许的:
<input v-on:keyup.13="submit">

Vue 提供了绝大多数常用的按键码的别名:

可以通过全局 config.keyCodes 对象自定义按键修饰符别名:

// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112

系统修饰键

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

七、计算属性和侦听器

计算属性

在模板中放入太多的逻辑会让模板过重且难以维护,当你想要在模板中多次引用此处功能时,就会更加难以处理。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

这时有以下两个方案来解决:

  1. 使用方法把这种复杂逻辑封装起来
  1. 使用计算属性

计算属性是 Vue 提供的一大特色,他定义在 computed 选项中。顾名思义,它一种带有行为的属性。
计算属性和方法的区别:

<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: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

我们提供的函数将用作属性 vm.reversedMessage 的 getter 函数,也可以这样写:

computed: {
  // 计算属性的 getter
  reversedMessage:  {
    get() {
      return this.message.split('').reverse().join('')
    }
  }
}

Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会重新计算并更新。

计算属性用于进行控件渲染的时候,通常控件那边用 v-model 进行双向绑定,而计算属性定义 get() 和 set() 函数,两者结合。

侦听属性 watch

Vue 为我们提供了用于监视数据变化的 watch 选项,你可以通过这个特定根据数据的变化做出对应的业务处理。当需要在数据变化执行异步或开销较大时,这个方法是最为有用的。
引用类型只能监视一层,无法监视内部子成员的改变。如果监视数据是数组或者对象需要配置深度 watcher:deep: true

八、Class与Style绑定

参考官网:https://cn.vuejs.org/v2/guide/class-and-style.html

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。
例如:<h1 class="red thin">Hello World</h1>
因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

绑定 HTML Class

对象语法

我们可以传给 v-bind:class 一个对象,以动态地切换 class:
例如:

<h1 :class="{ 'red': true, 'thin': true, 'italic': false, 'active': false }">Hello World</h1>

或者:

<h1 :class="classObj">Hello World</h1>

在 data 选项中定义这个对象,对象的属性是类名,可带引号,也可不带引号:

data: {
  classObj: { red: true, thin: true, italic: false, active: false }
}

我们也可以绑定一个返回对象的计算属性。这样可以根据 data 选项中值来渲染对应的样式。例如:

<div v-bind:class="classObject"></div>
data: {
  isActive: true,
  error: null
},
computed: {
  classObject: function () {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}
数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表。
例如:<h1 :class="['thin', 'italic']">Hello World</h1>
如果你也想根据条件切换列表中的 class,可以用三元表达式。
例如: <h1 :class="['thin', 'italic', isActive?'active':'']">Hello World</h1>
在数组语法中也可以使用对象语法,像这样在数组中使用对象来代替三元表达式,可以提高代码的可读性。<h1 :class="['thin', 'italic', {'active':isActive} ]">Hello World</h1>

用在组件上

当在一个自定义组件上使用 class 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。
例如,如果你声明了这个组件:

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})

然后在使用它的时候添加一些 class:
<my-component class="baz boo"></my-component>
HTML 将被渲染为:
<p class="foo bar baz boo">Hi</p>
isActive 为 true 时,HTML 将被渲染成为:
<p class="foo bar active">Hi</p>

绑定内联样式

对象语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:

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

直接绑定到一个样式对象通常更好,这会让模板更清晰:

<div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

同样的,对象语法常常结合返回对象的计算属性使用。

数组语法

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:

<h1 :style="[ styleObj1, styleObj2 ]">Hello World</h1>
data: {
  styleObj1: { color: 'red', 'font-weight': 200 },
  styleObj2: { 'font-style': 'italic' }
}
自动添加前缀

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

九、自定义指令

网址:https://cn.vuejs.org/v2/guide/custom-directive.html

1. What?

除了使用 Vue 提供的内置指令(例如 v-modelv-show)之外,我们可以自定义一些自己的指令。

2. When?

当需要不可避免的操作 DOM 的时候,使用自定义指令来解决。

3. How?

(1)注册

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

参数说明:
第一个参数:自定义指令的名字
第二个参数:配置指令的生命钩子函数(当符合一定的时机调用的方法叫做钩子函数)

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

(2)使用

<!-- 当页面加载的时候时,该元素将获得焦点-->
<input v-focus>
4. 指令的生命钩子函数

(1)一个指令定义对象可以提供如下几个钩子函数 (均为可选):

bind 与 inserted 异同
相同之处是一上来就执行一次,以后再也不会执行。
不同之处是 bind 中拿不到父元素,inserted可以拿到父元素。
(如果需要操作指令的父元素,则需要写到 inserted 中)

update 和 componentUpdated 异同
相同之处是都是作用该指令的模板发生更新的时候会触发调用。
不同之处是update 拿到的是数据改变视图之前的 DOM 内容,componentUpdated 拿到的是数据改变视图之后的 DOM 内容。

(如果你需要获取数据改变视图之前的内容,则把代码写到 update 中; 如果需要获取数据改变视图之后的内容,则把代码写到componentUpdated 中)

(2)钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。

案例:模拟 v-show 实现,根据值的真假来显示或隐藏该指令的元素
只需要在指令第一次绑定到元素时(bind)和指令对应的值更新时(update)改变该 DOM 元素。

Vue.directive('myShow', {
    bind: function (el, binding) {
        if(binding.value) {
            el.style.display = 'block'
        } else {
            el.style.display = 'none'
        }
    },
    update: function (el,binding) {
        if(binding.value) {
            el.style.display = 'block'
        } else {
            el.style.display = 'none'
        }
    }
})

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。我们可以采取类似以下的简写形式来实现与上面相同的功能。

Vue.directive('myShow', function (el, binding) {
    if(binding.value) {
        el.style.display = 'block'
    } else {
        el.style.display = 'none'
    }
})

(3)对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。例如:
HTML:

<div v-demo="{ color: 'white', text: 'hello!' }"></div>

JavaScript:

Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

十、过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。

过滤器的定义

全局定义

在创建 Vue 实例之前全局定义过滤器:

Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

new Vue({
  // ...
})
局部定义

可以在一个组件的选项中定义本地的过滤器:

filters: {
  capitalize: function (value) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
  }
}

过滤器的使用

<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。

开发与调试

为了方便调试和观察 Vue 应用,我们可以使用 Vue 官方开发的一个浏览器插件:Vue Devtools 来辅助调试。Chrome 商店可以安装该插件。
使用:

上一篇 下一篇

猜你喜欢

热点阅读