Vue的应用实例和组件实例

6,247 阅读4分钟

前言

这个月开始重新开始学习Vue3,从理解基本使用到模拟实现!

相关文章如下:

  1. 模拟实现Vue3初始化流程
  2. 模拟实现所有Vue3响应式API(上)

本文是Vue3系列的第3篇,关于应用实例和组件实例,基本目录如下:

image.png

创建一个Vue的应用实例

这部分主要讲以下3点:

image.png

1. 通过createApp函数创建Vue的应用实例

代码如下:

const app = Vue.createApp({ /* 相关选项配置 */ })

app即是应用实例

2. 返回的应用实例可以用于注册全局组件

比如:

app.component('Xxx', XxxComponent)

3. 应用实例上有很多方法都允许链式调用

比如:

Vue.createApp({ /* 相关选项配置 */ })
    .component('Xxx', XxxComponent)

原因在于,它们都是返回同一个app实例

根组件

这部分主要讲以下几点:

image.png

1. 利用createApp创建实例时需要传递一个选项,表示根组件的配置

比如,我们使用vite创建的项目中,有个main.js文件

//main.js
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

createApp(App).mount('#app')

上述代码中所传递的App即是根组件的配置

对应找到App.vue文件看看

//App.vue
//.....Omit some code.....
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

这里可以看到它导出的东西,我们干脆一探究竟,在看看子组件HelloWorld.vue

//components/HelloWorld.vue
//.....Omit some code.....
<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      count: 0
    }
  }
}
</script>

于是我们可以看到这个组件的配置有namepropsdata等,在实际使用中配置会更加丰富一些,之后会具体讲到

2. 可通过mount方法将一个应用挂载到一个DOM中,当挂载时,根组件会作为渲染的起点。需要注意:mount返回的是根组件实例,而不是应用实例了

为了看清楚,我们可以将app应用实例和根组件实例打印出来看

const app = createApp(App)
console.log(app);
console.log(app.mount('#app'));

结果如下:

image.png

可以看到两者是不一样的!

3. 一个根组件可以包含n个子组件,每个组件将有自己的组件实例,这些组件实例都共享同一个应用实例

还是以vite创建的Vue3项目为例,App组件中还包含子组件HelloWorld

import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  }
}

除此之外,你还可以添加其他自定义的组件

4. 本质上,根组件与其他组件是一样的

都是组件,两者并没有什么不同,包括行为和传递的配置其实都是一样的,只是根组件作为根,其他组件作为根组件的子组件而已

组件配置选项

这部分主要讲以下4点:

image.png

1. data中定义的属性都是通过组件实例暴露

比如在App组件中的配置data,里面定义一个属性name

data() {
    return {
      name: 'Alice'
    }
}

然后我们通过组件实例来获取到,需要注意不是应用实例

const app = createApp(App)
const vm = app.mount('#app')
console.log(app.name) // undefined
console.log(vm.name) // Alice

2. 其他选项如methods,props,computed,inject 和 setup,当中定义的属性也会添加到组件实例中

其实就在导出的配置选项中填入需要配置的东西即可

{
  name: 'Xxx',
  props: {...},
  data() {
    return {
      //...
    }
  },
  setup(){
      //....
  }
  //等等
}

3. 组件实例的所有属性,都可以在组件的模板中访问

比如HelloWorld组件中的count属性

//components/HelloWorld.vue
<template>
  <h1>{{ msg }}</h1>
  <button @click="count++">count is: {{ count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      count: 0
    }
  }
}
</script>

4. 组件实例还存在一些内置属性,如$attrs$emit

前面有个$,是为了避免与用户定义的属性发生冲突

生命周期钩子函数

这里主要讲以下5点内容

image.png

1. 每个组件在被创建时都会经过一系列的初始化过程,这个过程中会运行一些生命周期钩子函数

这个过程会包括模板编译、挂载、数据变化、更新DOM等等

2. 作用是,用户可以在组件的不同阶段添加自己的代码

例如我在组件挂载的时候执行一些操作

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3.0 + Vite" />
  <h1>{{name}}<h1>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data() {
    return {
      name: 'Alice'
    }
  },
  mounted(){
    console.log(`组件挂载了,修改name属性~`);
    this.name = 'Tom'
  }
}
</script>

结果如下

image.png

可以看到,我们通过钩子函数mounted,成功修改了name的值

3. 常见的钩子函数,如created、mounted、updated 和 unmounted等等

其实还有很多,由于都列出来没多大意义。后面用到的时候我再详细讲解!

4. 里头this指向调用它的当前活动实例

其实就是当前组件实例,上个例子已经试过了

this.name = 'Tom'

5. 注意:不要在选项配置的属性中使用箭头函数,也不要在钩子函数的回调中使用箭头函数,原因是箭头函数中没有this

箭头函数没有this,所以如果使用箭头函数,它会一直向上找,直至找到为止!为了避免出错,一般都不要这样写

mounted: () => {...}

总结

所有内容总结为一图,如下

image.png

END

以上就是关于应用实例和组件实例的所有内容

如有问题,欢迎留言告知,感谢~