Skip to content

实例

创建一个实例

 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
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Todolist</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root"> 
        <div @click="handleClick">
            {{ message }}
        </div>
        <item></item>
    </div>
    <script>
        // 组件也是一个实例
        Vue.component('item', {
            template: '<div>hello item</div>'
        })
        // 根实例
        var vm = new Vue({
            el: "#root",
            data: {
                message: 'hello world'
            },
            methods: {
                handleClick: function() {
                    alert('hello')
                }
            }
        })
    </script>
</body>
</html>

一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。举个例子,一个 todo 应用的组件树可以是这样的:

1
2
3
4
5
6
7
8
根实例
└─ TodoList
   ├─ TodoItem
   │  ├─ DeleteTodoButton
   │  └─ EditTodoButton
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics

数据与方法

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 我们的数据对象
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 中的属性才是响应式的。也就是说如果你添加一个新的属性,比如:

1
vm.b = 'hi'

那么对 b 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:

1
2
3
4
5
6
7
data: {
  newTodoText: '',
  visitCount: 0,
  hideCompletedTodos: false,
  todos: [],
  error: null
}

这里唯一的例外是使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var obj = {
  foo: 'bar'
}

Object.freeze(obj)

new Vue({
  el: '#app',
  data: obj
})
1
2
3
4
5
<div id="app">
  <p>{{ foo }}</p>
  <!-- 这里的 `foo` 不会更新! -->
  <button v-on:click="foo = 'baz'">Change it</button>
</div>

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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 实例。

注意:

不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。

生命周期图示

beforeCreate

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div id="app">hello world</div>
<script>
    // 生命周期函数就是 vue 实例在某一个时间点会自动执行的函数
    var vm = new Vue({
        el: "#app",
        beforeCreate: function() {
            console.log("beforeCreate");
        }
    })
</script>

created

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<div id="app">hello world</div>
<script>
    // 生命周期函数就是 vue 实例在某一个时间点会自动执行的函数
    var vm = new Vue({
        el: "#app",
        beforeCreate: function() {
            console.log("beforeCreate");
        },
        created: function() {
            console.log("created")
        }
    })
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app"></div>
<script>
    var vm = new Vue({
        el: "#app",
        template: "<div>hello world</div>",
        beforeCreate: function() {
            console.log("beforeCreate");
        },
        created: function() {
            console.log("created");
        },
        beforeMount: function() {
            console.log(this.$el);
            console.log("beforeMount");
        },
        mounted: function() {
            console.log(this.$el);
            console.log("mounted");
        }
    })
</script>

 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
<div id="app"></div>
<script>
    var vm = new Vue({
        el: "#app",
        template: "<div>{{ test }}</div>",
        data: {
            test: "hello world",
        },
        beforeCreate: function() {
            console.log("beforeCreate");
        },
        created: function() {
            console.log("created");
        },
        beforeMount: function() {
            console.log(this.$el);
            console.log("beforeMount");
        },
        mounted: function() {
            console.log(this.$el);
            console.log("mounted");
        },
        beforeDestroy: function() {
            console.log("beforeDestroy");
        },
        destroyed: function() {
            console.log("destroyed");
        },
        beforeUpdate: function() {
            console.log("beforeUpdate");
        },
        updated: function() {
            console.log("updated");
        }
    })
</script>