Vue实例

  1. 1. 一、创建一个Vue实例
    1. 1.1. 二、数据与方法
  2. 2. 三、模板语法
    1. 2.1. 使用 JavaScript 表达式
    2. 2.2. 指令
    3. 2.3. v-model
    4. 2.4. 修饰符
  3. 3. 四、计算属性和侦听器
    1. 3.1. 我们为什么需要缓存?
  4. 4. 五、侦听器
  5. 5. 六、Vue操作数组
  6. 6. 七、过滤器
    1. 6.1. 全局过滤器
    2. 6.2. 本地过滤器

现在算来已经有四个月没学习vue了,这段时间大部分都用在spring框架上,vue忘的也差不多了,但今天重新启航!开卷!

一、创建一个Vue实例

​ 当一个 Vue 实例被创建时,它将 data对象中的所有的 属性都会加入到 Vue 的响应式系统中。当这些 属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 我们的数据对象
var data = { a: 1 }

// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})

// 获得这个实例上的 property
// 返回源数据中对应的字段
vm.a == data.a // => true

// 设置 property 也会影响到原始数据
vm.a = 2
data.a // => 2

​ 当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 data 中的 属性才是响应式的。也就是说如果你添加一个新的属性,那么对这个新属性的改动将不会触发任何视图的更新。

​ 如果你知道你会在晚些时候需要使用一个 property属性,但是一开始不需要使用它们,那么你可以设置一些初始值,这样后面就可以用到了。

Object.freeze(),这会阻止修改现有的 property,也意味着响应系统无法再追踪变化。

二、数据与方法

​ 除了数据 的property,Vue 实例还提供了一些有用的实例 property 与方法。它们都有前缀 $,以便与用户定义的 property 区分开来。

1
2
3
4
5
6
7
8
9
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})

vm.$data === data // => true
vm._data == data // => true
vm.$el === document.getElementById('example') // => true

注:这些的属性加不加$,都一样,只是多了一个写法,好区分开。

不要在选项 property 或回调上使用箭头函数,比如 created: () => console.log(this.a)vm.$watch('a', newValue => this.myMethod())

因为箭头函数并没有 thisthis 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefinedUncaught TypeError: this.myMethod is not a function 之类的错误。

三、模板语法

通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

1
<span v-once>这个将不会改变: {{ msg }}</span>

双大括号会将数据解释为普通文本而输出,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html指令:

1
2
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

使用 JavaScript 表达式

迄今为止,在我们的模板中,我们一直都只绑定简单的 property 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

1
2
3
4
5
6
7
{{ number + 1 }}

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

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

<div v-bind:id="'list-' + id"></div>

​ 这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。

1
2
3
4
5
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}

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

指令

  1. v-if 指令将根据表达式 seen的值的真假来插入/移除

    元素。

1
<p v-if="seen">现在你看到我了</p>

​ 2. 一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 的属性:

1
<a v-bind:href="url">...</a>

在这里 href 是参数,告知 v-bind 指令将该元素的 href 属性与表达式 url 的值绑定。

v-bind缩写

1
2
3
4
5
6
7
8
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
  1. v-on 指令,它用于监听 DOM 事件:
1
<a v-on:click="doSomething">...</a>

在这里参数是监听的事件名。

缩写

1
2
3
4
5
6
7
8
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

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

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
  1. 同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:
1
<a v-on:[eventName]="doSomething"> ... </a>

在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus

​ 在 DOM 中使用模板时 (直接在一个 HTML 文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写:

​ 缩写写法看起来可能与普通的 HTML 略有不同,但 :@ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的,但随着你更深入地了解它们的作用,你会庆幸拥有它们。

v-model

v-model中还可以使用一些修饰符来实现某些功能:

  1. v-model.lazy 只有在input输入框发生一个blur时才触发,也就是延迟同步到失去焦点时。
  2. v-model.trim 将用户输入的前后的空格去掉。
  3. v-model.number 将用户输入的字符串转换成number。

修饰符

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

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

四、计算属性和侦听器

对于任何复杂逻辑,你都应当使用计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div id="app">
<div id="example">
<p>Original message: "{{message}}"</p>
<p>Computed reversed message: "{{reversedMessage}}"</p>
</div>
</div>

<script>
var vm = new Vue({
el: '#app',
data() {
return {
message: 'Hello'
}
},

computed: {
// 计算属性的getter
reversedMessage() {
// this 指向vm实例
return this.message.split('').reverse().join('')
}
}

})
</script>

vm.reversedMessage 的值始终取决于 vm.message 的值。

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

​ 我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

1
2
3
4
5
computed: {
now: function () {
return Date.now()
}
}

我们为什么需要缓存?

​ 假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用method来替代。

五、侦听器

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

watch能够监听数据的改变。监听之后会调用一个回调函数。 此回调函数的参数有两个:

  1. 更新后的值(新值)
  2. 更新前的值(旧值)

六、Vue操作数组

​ Vue 提供一组观察数组的变异方法(就是这些方法会改变原始数组,所以才会被Vue检测到),使用它们就可以触发视图更新。 这些方法有7个:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

七、过滤器

过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据。

过滤器分全局过滤器和本地过滤器(局部过滤器)。

全局过滤器

下面定义一个全局过滤器,用于在数据前加上大写的VUE。需要注意的是,全局过滤器定义必须始终位于Vue实例之上,否则会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="app">
{{message | toAdd}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.filter("toAdd", function(value) {
return 'VUE' + value
})
var demo = new Vue({
el: '#app',
data: {
message: '过滤器',
}
})
</script>

注意:

  1. Vue.filter() 后有两个参数:过滤器名,过滤器处理函数。
  2. 过滤器处理函数也有一个参数:要过滤的数据。

本地过滤器

本地过滤器存储在vue组件中,作为filters属性中的函数,我们可以注册多个过滤器存储在其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
<p>{{message | Reverse}}</p>
<p>{{message | Length}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var demo = new Vue({
el: '#app',
data: {
message: '过滤器',
},
filters: {
Reverse: function(value) {
if (!value){
return '';
}
return value.toString().split('').reverse().join('');
},
Length: function(value) {
return value.length;
},
},
})
</script>