Vue实例

作者 新城 日期 2017-09-29
Vue
Vue实例
创建一个vue实例
1
2
3
var vm = new Vue({
// 选项
})
数据与方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})
// 他们引用相同的对象!
vm.a === data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ... 反之亦然
data.a = 3
vm.a // => 3

当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时 data 中存在的属性是响应式的。

除了 data 属性,Vue 实例暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。例如:

1
2
3
4
5
6
7
8
9
10
11
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})

实例生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们自己的代码。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

1
2
3
4
5
6
7
8
9
10
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"

也有一些其它的钩子,在实例生命周期的不同场景下调用,如 mounted、updated、destroyed。钩子的 this 指向调用它的 Vue 实例。

使用javascript表达式
1
2
3
4
5
6
7
**那个绑定只能包含单个表达式**
{{ message.split('').reverse().join('') }}
**错误示例**
//{{ if (ok) { return message } }}

v-bing:href 缩写 :href
v-on:click 缩写 @click

计算属性和观察者

计算属性
模板内部的表达式相对来说是便利的,在模板内不放如果的表达式的话显得过于臃肿,

1
2
3
<div>
{{message.split('').reverse().join('')}}
</div>

如果多个地方用到 比较难以维护

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id='demo'>
<p>{{messge}}</p>
<p>{{reversedMessage}}</p>
</div>
--------js-------
var vm = new Vue({
el:'#demo',
data:{
message:'hello word'
},
computed:{ //针对某个属性进行计算 设置名称
reversedMessage:function(){
return this.message.split('').reverse().join('')
}
}
})

当属性message变化的时候 revenseMessage也会发生改变

计算属性的缓存vs方法

上诉的方式我也可以使用生命一些方法去 代替

1
2
3
4
5
6
<p>{{reverseMessage}}</p>
methods:{
reverseMessage:function(){
return this.message.split('').reverse().join('')
}
}

也能达到同样的效果

方法需要多次调用计算
computed 设置有缓存不需要多次计算 效率相对来说比较高

计算属性vs被观察者属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其他什么人吃的东西' }
]
}
})
//代替
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
计算属性

计算属性默认只有getter 也可以提供一个setter属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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]
}
}
}

观察者(重点)

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 question 发生改变,这个函数就会运行
question: function (newQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
// _.debounce 是一个通过 lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// ajax 请求直到用户输入完毕才会发出
// 学习更多关于 _.debounce function (and its cousin
// _.throttle),参考:https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
// 这是我们为用户停止输入等待的毫秒数
500
)
}
})
</script>

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的 watcher。这是为什么 Vue 通过 watch 选项提供一个更通用的方法,来响应数据的变化当你想要在数据变化响应时,执行异步操作或开销较大的操作,这是很有用的。

watch 监控变量是否发生变化 变化的话调用getAnswer()方法发送请求