应用实例

实验介绍

本章节主要是对 Vue 应用实例的讲解,我们都知道在 Vue 2.x 是通过 new Vue() 来创建 Vue 应用的,但是在 Vue 3.0 中不是这样的,使用 createApp() 来创建实例的。接下来我们就来好好讲讲 Vue 应用实例。

创建一个应用实例

我们在接着上个章节的实验的代码,删除多余的代码之后,我们打开 src/main.js,看到引入了一堆东西,我们看到最后一行代码最吸引我们的眼球,对的,就是他创建了一个应用实例,从 Vue 中导出了 createApp 静态方法,传入 App 组件,然后使用 use 方法传入 storerouter 等中间件,最后 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')


Vue 3 创建应用实例_java

其实我们知道 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 3 创建应用实例_java_02



更过的东西我们留在讲解 Vue API 的时候再深入讲解。