[翻译] vue3指南-03应用实例

944 阅读5分钟

Creating an Instance 创建一个实例

Every Vue application starts by creating a new application instance with the createApp function:

Vue应用从创建应用实例开始:

Vue.createApp(/* options */)

After the instance is created, we can mount it, passing a container to mount method. For example, if we want to mount a Vue application on <div id="app"></div>, we should pass #app:

实例创建之后,我们来挂载它——传一个容器元素mount方法.打个比方,如果想把Vue应用挂载一个<div id="app"></div>上,要传#app过去:

Vue.createApp(/* options */).mount('#app')

Although not strictly associated with the MVVM pattern, Vue's design was partly inspired by it. As a convention, we often use the variable vm (short for ViewModel) to refer to our instance.

Vue的设计是受MVVM模式启发的,但却不是严格依照它的模式来的. 按习惯, 我们常常使用变量vm来表示这个实例.

When you create an instance, you pass in an options object. The majority of this guide describes how you can use these options to create your desired behavior. For reference, you can also browse the full list of options in the API reference.

创建实例的时候,会传一个option对象进入.这个指南主要在讲怎么按你自己的想的行为去设置option. 作为参考,完整版API可以看这里.

A Vue application consists of a root instance created with createApp, optionally organized into a tree of nested, reusable components. For example, a todo app's component tree might look like this:

一个Vue应用由 一个root实例组成(createApp());然后,按照自己的想法/或者怎样,按一定方式地把应用组织成一颗嵌套,可复用组件树.比如,一个todo应用的组件树可能长这样:

Root Instance
└─ TodoList
   ├─ TodoItem
   │  ├─ DeleteTodoButton
   │  └─ EditTodoButton
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics

We'll talk about the component system in detail later. For now, just know that all Vue components are also instances, and so accept the same options object.

之后会详细聊组件系统.现在先大概知道:所有Vue组件都是实例,所以接受相同的option对象.

Data and Methods

When an instance is created, it adds all the properties found in its data to Vue's reactivity system. When the values of those properties change, the view will "react", updating to match the new values.

实例创建的时候,实例会把它data里面的所有属性(property们)添加到Vue的reactivity系统(响应系统). 当这些属性们的变化的时候,视图也会跟着“有反应(react)”——让和值保持一致.

(ps. 这里的 reactivity system. 就是讨论的很多的vue/next/packages/reactivity 新内容, 你会发现,上面的vm是一个Proxy对象. 到这,就和之前网上有很多读源码的帖子联系了起来——“Proxy去哪了,Proxy在哪里~”)

// Our data object
const data = { a: 1 }

// The object is added to the root instance
const vm = Vue.createApp({
  data() {
    return data
  }
}).mount('#app')

// Getting the property on the instance
// returns the one from the original data
vm.a === data.a // => true

// Setting the property on the instance
// also affects the original data
vm.a = 2
data.a // => 2

When this data changes, the view will re-render. It should be noted that properties in data are only reactive if they existed when the instance was created. That means if you add a new property, like:

当上面这个data对象值变化的时候,视图层也会重新渲染. 值得注意的是: 只有那些在建立实例的时候就已经存在于data内的属性,才会是响应的.

这就是说,如果你又新增了一个属性,比如:

vm.b = 'hi'

Then changes to b will not trigger any view updates. If you know you'll need a property later, but it starts out empty or non-existent, you'll need to set some initial value. For example:

那么,b的值的任何变化都不会触发任何视图更新.

如果你知道你以后会需要用一个属性——一个一开始是空的/不需要存在的属性,那你需要给他们一个初始值,比如:

data() {
  return {
    newTodoText'',
    visitCount0,
    hideCompletedTodosfalse,
    todos: [],
    errornull
  }
}

The only exception to this being the use of Object.freeze(), which prevents existing properties from being changed, which also means the reactivity system can't track changes.

唯一(不会响应的)的例外就是——使用了Object.freeze()方法,这方法禁止已有属性更新,也就使得reactivity system没办法跟踪了~

const obj = {
  foo'bar'
}

Object.freeze(obj)

const vm = Vue.createApp({
  data() {
    return obj
  }
}).mount('#app')
<div id="app">
  <p>{{ foo }}</p>
  <!-- this will no longer update `foo`! -->
  <button v-on:click="foo = 'baz'">Change it</button>
</div>

In addition to data properties, instances expose a number of useful instance properties and methods. These are prefixed with $ to differentiate them from user-defined properties. For example:

除了data的属性(property)们, 实例还暴露了一系列有用的实例属性和方法. 这属性/方法以$做前缀 来和 用户自定义属性区别开.

const vm = Vue.createApp({
  data() {
    return {
      a: 1
    }
  }
}).mount('#example')

vm.$data.a // => 1

In the future, you can consult the API reference for a full list of instance properties and methods.

之后,你可以去这个API参考去查阅实例属性和方法的完整列表.

Instance Lifecycle Hooks

Each instance goes through a series of initialization steps when it's created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called lifecycle hooks, giving users the opportunity to add their own code at specific stages.

每个实例,在他们创建的时候(created)都会进行一些列初始化.比如有: 建立data监测;编译模版;挂在实例到DOM上,data变化时更新DOM,等等... 在这个过程中,也会有一些生命周期钩子函数被调用——用来让用户/开发人员可以有机会把自己的需要的代码写入制定的生命周期阶段.

For example, the created hook can be used to run code after an instance is created:

比如,created会在实例被创建之后被调用:

Vue.createApp({
  data() {
    return {
      a1
    }
  },
  created() {
    // `this` points to the vm instance
    console.log('a is: ' + this.a// => "a is: 1"
  }
})

There are also other hooks which will be called at different stages of the instance's lifecycle, such as mounted, updated, and unmounted. All lifecycle hooks are called with their this context pointing to the current active instance invoking it.

当然,也有其他钩子会在实例不同生命周期被调用.有mounted,updatedunmounted...
所有钩子内的this上下文都指向调用这个钩子的当前实例.

TIP 提醒

Don't use arrow functions on an options property or callback, such as created: () => console.log(this.a) or vm.$watch('a', newValue => this.myMethod()). Since an arrow function doesn't have a this, this will be treated as any other variable and lexically looked up through parent scopes until found, often resulting in errors such as Uncaught TypeError: Cannot read property of undefined or Uncaught TypeError: this.myMethod is not a function.

别在 option的属性(property)或者回调函数 里用箭头函数. 像这样,created: () => console.log(this.a) or vm.$watch('a', newValue => this.myMethod()). 因为箭头函数不存在this. this回被当作一般变量(any other variable),然后向上(through parent scope)查找知道找到. 往往会导致一些报错:Uncaught TypeError: Cannot read property of undefined or Uncaught TypeError: this.myMethod is not a function.

Lifecycle Diagram 生命周期图

Below is a diagram for the instance lifecycle. You don't need to fully understand everything going on right now, but as you learn and build more, it will be a useful reference.

现在你没必要完全搞懂每个框框,随着你继续深入下去,这会是一个跟好的参考.

events - lifecycle
events - lifecycle