实验介绍
本章节主要是对 Vue 应用实例的讲解,我们都知道在 Vue 2.x 是通过 new Vue()
来创建 Vue 应用的,但是在 Vue 3.0 中不是这样的,使用 createApp()
来创建实例的。接下来我们就来好好讲讲 Vue 应用实例。
创建一个应用实例
我们在接着上个章节的实验的代码,删除多余的代码之后,我们打开 src/main.js
,看到引入了一堆东西,我们看到最后一行代码最吸引我们的眼球,对的,就是他创建了一个应用实例,从 Vue 中导出了 createApp
静态方法,传入 App
组件,然后使用 use
方法传入 store
,router
等中间件,最后 mount
挂载到 #app
元素上面:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
其实我们知道 createApp(App)
参数 App
就是一个组件,那么我们现在不给他传入一个 App
,我们以 options
方式传递进去呢?我们可以使用 defineComponent
的形式自己定义一个组件来替换我们的 App
组件,形式是一样的,只不过这是以 js
的形式呈现而已:
import { createApp, defineComponent } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
const com = defineComponent({
name: 'com',
template: `
<div>
{{msg}}
<button @click="click">按钮</button>
</div>
`,
data() {
return {
msg: '这是 com 组件'
}
},
methods: {
click() {
this.msg = "点击按钮改变 msg 的值"
}
}
})
createApp(com).use(store).use(router).mount('#app')
最后我们打开浏览器,localhost:8080
就可以看到效果了:
data 和 methods
当一个 createApp
创建 Vue 实例时,他会将 data
里面的所有的数据都加入 Vue 的响应式系统中,进行响应式监测,当这些数据变化时,页面上展示的数据就会及时更新,这样就能真正做到响应式。接下来我们还是在 src/main.js
来演示一下代码,我们按照上面的代码,先来定义一个 tempData
对象,将其解构到 data
函数返回的对象里面
import { createApp, defineComponent } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
let tempData = {
data: 1,
}
const com = defineComponent({
name: 'com',
template: `
<div>
{{msg}}
<br/>
{{data}}
<button @click="click">按钮</button>
</div>
`,
data() {
return {
msg: '这是 com 组件',
...tempData
}
},
methods: {
click() {
this.msg = "点击按钮改变 msg 的值"
this.data++
}
}
})
createApp(com).use(store).use(router).mount('#app')
我们下来看看浏览效果,我们可以看到解构之后的 tempData
中的 data
属性在 Vue 中有了响应性,在点击按钮之后每次加 1
操作,都会重新更新页面的值:
接下来,我们来定义 vm
,改变 vm.data 的值 为 2
:
let vm = createApp(com).use(store).use(router).mount('#app')
vm.data = 2 // 改变 data 的值,页面展示的数据就会变成 2
console.log(vm.data == tempData.data) // 看看是否是同一个值 false, 因为我们已经将 tempData 解构了
那有人会有疑问,假如我给 vm
加入一个之前从来没有定义过的值,会怎么样呢?值得注意的是只有当实例被创建时就已经存在于 data
中的 property 才是响应式的。也就是说如果你添加一个新的 property,比如:
vm.b = 10
他是否会直接响应到我们的页面上呢?我们来看看奇迹吧:
我们来看看浏览效果,我们发现我们从来没有定义过的属性,也是可以直接响应到我们的页面上的,至于原理我们暂时不讲,后面会讲到,我们先把基础的学会就行了:
其实我们可以回顾一下 Vue 2.x 确实是不会更新到我们的页面上的,因为此时的 b
属性他没有加入到 Vue 的响应式系统中进行监测,所以在 Vue 2.x 中 $set
的 API 就会显得必要些了,但是在 Vue 3.0 中我们可以看到或许我们并不需要 $set
的 API 了,所以自然而然就会被废除了。
Object.freeze()
为什么要讲解这个属性呢?因为在实际应用情况中,我们可能在展示一些仅仅只是展示的列表的数据,这些数据仅仅只是展示给用户看,并不需要响应式监测,所以我们可以使用这个属性来脱离 Vue 响应式系统的监测:
继续在 src/main.js
写下代码:
import { createApp, defineComponent } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
let foo = Object.freeze({
foo: 3
}) // 冻结对象
const com = defineComponent({
name: 'com',
template: `
<div>
{{foo}}
<br/>
<button @click="click">按钮</button>
</div>
`,
data() {
return foo
},
methods: {
click() {
this.foo++
}
}
})
createApp(com).use(store).use(router).mount('#app')
当我们点击按钮,发现控制台会报错:
更过的东西我们留在讲解 Vue API 的时候再深入讲解。