随手记Vue3.0文档阅读差异(1)

547 阅读4分钟

引言

本文为作者记录自身所理解的2.*与3.0差异,主要是帮助作者自身理解3.0,并非严谨的教学,如出现不准确的地方,请勿责怪,相互学习。

开始

首先根据自己阅读文档后,把整体在使用上的差异基于自己对Vue这个框架的理解分为了四个部分,后续本人讲根据顺序进行编写。

  • 配置
  • API
  • 组件/指令
  • 组合API

配置

app.config

先看官方介绍

image.png 然后我们即可在当前对象下挂载选项

  • errorHandler
  • warnHandler
  • globalProperties
  • isCustomElement
  • optionMergeStrategies
  • performance 其中与2.*版本存在差异的就是globalPropertiesisCustomElement

globalProperties

根据官方的一个介绍情况,实际上就是来做一些全局属性方法的,可以代2.*原有的两种做法

  • 全局 allmixin
// main.js
const allMixin = {
    data () {
        return {
            someConfig: 'xxxx'
        }
    },
    methods: {
        someFn () {
            console.log('I am someFn')
        }
    }
}
// 全局混入
Vue.mixin(allMixin)

// xxx.vue
console.log(`all mixin data have someConfig ${vm.someConfig}`)
// 输出'all mixin data have someConfig xxxx'
vm.someFn()
// 'I am someFn'

全局混入想要达到的目的就是在全局加入一些Vue的option配置,statusmethod其实都是可以通过globalProperties这个方式来进行替代

  • 原型继承 Vue.property.xxxx
// main.js
Vue.prototype.$config = {
    someConfig: 'xxxx',
    someFn: () => {
        console.log('I am someFn')
    }
}

// xxx.vue
console.log(`all mixin data have someConfig ${vm.$config.someConfig}`)
// 输出'all mixin data have someConfig xxxx'
vm.$config.someFn()
// 'I am someFn'

这种相当于利用了JS原型继承的方式,让构造实例通过原型查找,找到对应的属性方法,相对来说跟我们今天要说的globalProperties 也是比较类似的,我们来看下globalProperties的官方使用案例

app.config.globalProperties.foo = 'bar'

app.component('child-component', {
  mounted() {
    console.log(this.foo) // 'bar'
  }
})

实际上会发现跟我们的第二种方式相当的接近,但是作者简单看了一下实现的做法上还是不太一样的,扫了一下源码应该是通过在this或者我们的vm上通过proxy的get拦截进行的处理,直接进行的取值判断~,另一点globalProperties的命名实际上也进行了一个语义传达,更加方便其他开发者阅读代码。

isCustomElement

首先我们先关注一下官方的介绍 image.png 从介绍看来,是提供了接口用来,传递一个过滤方法,方便Vue排查组件之外的自定义组件,作者会想起之前的某一应用场景,简单跟大家分享一下,我司存在微信引流的业务需求,需要从微信引流到具体APP,这里会涉及到微信开放平台中的能力微信内网页跳转APP功能,在进行开发的过程中机会发现无法直接在单文件组件中使用wx-open-launch-app 那么相当于在新能力下可以通过一下代码避免这个问题

app.config.isCustomElement = tag => tag.startsWith('wx-')

isCustomElement相当于提供了第三方自定义组件的拓展,使得DOM整体结构更语义化~

emits

这个算是一个比较大的变动,原有在2.*中,子组件事件都是通过vm.$emit(...)方式进行向上传递,但是事件命名本身是没有进行约定的,也没有对应的返回校验。如果是在这样的背景下针对event所返回的参数实际上是需要校验的,毕竟在这个场景下,我们没有办法确保说给到的参数一定是我们预期的内容(当然你可以使用TS去做相关静态类型检查),但毕竟不是一个完善的方案。而3.0中所提供的emits实际上来说就是变相的增加了我们整体组件的可靠性~,当然这个也是要基于大家遵守规范并使用起来的情况。

下面我们就来看一下emits官方的具体使用案例

const app = Vue.createApp({})

// 数组语法
app.component('todo-item', {
  emits: ['check'],
  created() {
    this.$emit('check')
  }
})

// 对象语法
app.component('reply-form', {
  emits: {
    // 没有验证函数
    click: null,

    // 带有验证函数
    submit: payload => {
      if (payload.email && payload.password) {
        return true
      } else {
        console.warn(`Invalid submit event payload!`)
        return false
      }
    }
  }
})

renderTracked

新声明周期,主要是在渲染阶段中数据被track一个情况,如下案例

vue.template

<template>
  <div class="home">
    {{test}}
    {{test1}}
  </div>
</template>

vm.option

export default defineComponent({
  data () {
    return {
      test: '1',
      test1: '2'
    }
  },
  renderTracked (event) {
    console.log(event)
  }
})

那么我们在控制台可以得到以下输出内容

image.png 可以通过以上内容,在渲染阶段知道具体哪一个属性被具体track,就可以排查对应的比如不应该被track的元素被track 或者 应该被track的元素没有被track

renderTriggered

同理以上内容,当前生命周期也是表达了在渲染期间被triggered的属性

API

defineComponent

从命名上看,主要是用来定义某一个组件的,但实际上底层只是直接返回了对象内容或者是当成setup声明周期进行构造

// packages/runtime-core/src/apiDefineComponent.ts
export function defineComponent(options: unknown) {
  return isFunction(options) ? { setup: options, name: options.name } : options
}

作用上Vue官方实际上也做了响应说明

image.png

defineAsyncComponent

定义一个异步组件,实际上这里我们在接触Vue-router的懒加载的时候也有过类似体验,只不过Vue的这个api可以协助我们以更小的细粒度去定义相关组件,具体内容不做赘述,点击这里跳转官方文档

defineAsyncComponent, resolveDynamicComponent, resolveDirective

可以通过名称对相对应的内容进行一定的解析,但是目前来说用途不是特别明确,感兴趣的小伙伴可以自己翻阅官方文档,资深大佬欢迎留言教育

createRenderer

自定义render构造器,实际上个人人为这个就是为跨端留的口子。毕竟现有的宿主环境已经是比较多变啦,比如可以做weex这一类跨段的支持啊等,当然这个就是个人拙见,不同看法欢迎讨论

组件/指令

teleport

要理解<teleport>,可以先简单的联想一下slot的用法, <slot>是一种从组件外部注入模版的方式如下

<!-- 子组件模版 children -->
<template>
    <div class="children-wrap">
        <slot />
    </div>
</template>

<!-- 父组件模版 -->
<template>
    <children>
        <div>我来自父组件</div>
    </children>
</template>

<!-- 最后渲染 -->
<div class="children-wrap">
    <div>我来自父组件</div>
</div>

那么实际上就是<teleport>就是反过来,从内部像外部透出~,但是经过本人测试,其实是没有像是类似slot的效果的,主要是没有办法移动到父组件所定义的模版内,只能迁移到HTML文档内的class/id/tag中。当然也有一定的意义,比如官方提到说

image.png

当然除了模态框,也有其他的一些场景,比如布局上的一些操作,头部,底部,抽屉组件等。

v-is

这个指令官方的api已经说的比较清晰啦~,这里只做提及不做说明,点击这里查看

组合API

这个基本为3.0最大的转变,最好是专门的出一期进行使用记录~~

本期就先这样啦,大家再见~ 有问题欢迎留言讨论,按照本文进行技术学习的同学,概不负责!