createApp

  1. import { createApp } from "vue";
  2. import App from "./App.vue";
  3. createApp(App).mount("#app");

为什么
相比Vue2 new Vue()创建Vue实例,从同一个Vue构造函数创建的每个根实例共享相同的全局配置:

  • 在测试阶段,全局配置很容易意外地污染其他测试用例
  • 全局配置使得在同一页面上的多个“app”之间共享同一个 Vue 副本非常困难,但全局配置不同。

在应用之间共享配置

在应用之间共享配置 (如组件或指令) 的一种方法是创建工厂功能,如下所示

  1. import { createApp } from 'vue'
  2. import Foo from './Foo.vue'
  3. import Bar from './Bar.vue'
  4. const createMyApp = options => {
  5. const app = createApp(options)
  6. app.directive('focus', /* ... */)
  7. return app
  8. }
  9. createMyApp(Foo).mount('#foo')
  10. createMyApp(Bar).mount('#bar')
  11. //现在,Foo 和 Bar 实例及其后代中都可以使用 focus 指令。

组合式 API

为了更关注逻辑
CgFBIl_Em56AQqcBAAWd2mm7Wbs000.gif

  1. setup() {
  2. // ref 是一个函数,它接受一个参数,返回的就是一个神奇的 响应式对象 。
  3. 我们初始化的这个 0 作为参数包裹到这个对象中去,在未来可以检测到改变并作出对应的相应。
  4. const count = ref(0)
  5. const double = computed(() => {
  6. return count.value * 2
  7. })
  8. const increase = () => {
  9. count.value++
  10. }
  11. return {
  12. count,
  13. increase,
  14. double
  15. }
  16. }

为什么不用之前的组件的选项 data、computed、methods、watch 组织逻辑在大多数情况下都有效。然而,当我们的组件变得更大时,逻辑关注点的列表也会增长。这可能会导致组件难以阅读和理解,尤其是对于那些一开始就没有编写这些组件的人来说。而通过setup可以将该部分抽离成函数,让其他开发者就不用关心该部分逻辑了.

reactive

  1. import { ref, computed, reactive, toRefs } from 'vue'
  2. interface DataProps {
  3. count: number;
  4. double: number;
  5. increase: () => void;
  6. }
  7. setup() {
  8. const data: DataProps = reactive({
  9. count: 0,
  10. increase: () => { data.count++},
  11. double: computed(() => data.count * 2)
  12. })
  13. const refData = toRefs(data)
  14. return {
  15. ...refData
  16. }
  17. }

使用 ref 还是 reactive 可以选择这样的准则

  • 第一,就像刚才的原生 javascript 的代码一样,像你平常写普通的 js 代码选择原始类型和对象类型一样来选择是使用 ref 还是 reactive。
  • 第二,所有场景都使用 reactive,但是要记得使用 toRefs保证 reactive 对象属性保持响应性。

    toRefs()函数可以将reactive()创建出来的响应式对象,转换为普通对象,只不过这个对象上的每个属性节点,都是ref()类型的响应式数据

生命周期

  • beforeCreate -> 不需要
  • created -> 不需要
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeUnmount -> onBeforeUnmount
  • unmounted -> onUnmounted
  • errorCaptured -> onErrorCaptured
  • renderTracked -> onRenderTracked
  • renderTriggered -> onRenderTriggered

watch

  1. // watch 简单应用
  2. watch(data, () => {
  3. document.title = 'updated ' + data.count
  4. })
  5. // watch 的两个参数,代表新的值和旧的值
  6. watch(refData.count, (newValue, oldValue) => {
  7. console.log('old', oldValue)
  8. console.log('new', newValue)
  9. document.title = 'updated ' + data.count
  10. })
  11. // watch 多个值,返回的也是多个值的数组
  12. watch([greetings, data], (newValue, oldValue) => {
  13. console.log('old', oldValue)
  14. console.log('new', newValue)
  15. document.title = 'updated' + greetings.value + data.count
  16. })
  17. // 使用 getter 的写法 watch reactive 对象中的一项
  18. watch([greetings, () => data.count], (newValue, oldValue) => {
  19. console.log('old', oldValue)
  20. console.log('new', newValue)
  21. document.title = 'updated' + greetings.value + data.count
  22. })

全局 API 修改

Vue2 的全局配置

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. Vue.config.ignoredElements = [/^app-/]
  4. Vue.use(/* ... */)
  5. Vue.mixin(/* ... */)
  6. Vue.component(/* ... */)
  7. Vue.directive(/* ... */)
  8. Vue.prototype.customProperty = () => {}
  9. new Vue({
  10. render: h => h(App)
  11. }).$mount('#app')

Vue3 的修改

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. const app = createApp(App)
  4. // 这个时候 app 就是一个 App 的实例,现在再设置任何的配置是在不同的 app 实例上面的,
  5. 不会像vue2 一样发生任何的冲突。
  6. app.config.isCustomElement = tag => tag.startsWith('app-')
  7. app.use(/* ... */)
  8. app.mixin(/* ... */)
  9. app.component(/* ... */)
  10. app.directive(/* ... */)
  11. app.config.globalProperties.customProperty = () => {}
  12. // 当配置结束以后,我们再把 App 使用 mount 方法挂载到固定的 DOM 的节点上。
  13. app.mount(App, '#app')