2.Vue2与Vue3的全局配置API变化区别
# createApp
Vue2.x创建实例并且挂载DOM上
import Vue from "vue";
import App from './App.vue'
new Vue({
render: (h) => h(App)
}).$mount("#app");
2
3
4
5
6
Vue3新增api===>createApp源码地址 创建实例
createApp 会产生一个 app 实例,该实例拥有全局的可配置上下文
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
2
3
# createApp做了什么
调用 createApp 将返回一个 应用实例,这是一个 Vue 3 中的全新概念。 应用实例将暴露一个现有全局 API 的子集。大致上讲就是, 任意能全局干预到 Vue 的行为的 API 现在都被转移到了应用实例下。
export const createApp = ((...args) => {
const app = ensureRenderer().createApp(...args)
if (__DEV__) {
injectNativeTagCheck(app)
}
const { mount } = app
app.mount = (containerOrSelector: Element | string): any => {
const container = normalizeContainer(containerOrSelector)
if (!container) return
const component = app._component
if (!isFunction(component) && !component.render && !component.template) {
component.template = container.innerHTML
}
// clear content before mounting
container.innerHTML = ''
const proxy = mount(container)
container.removeAttribute('v-cloak')
container.setAttribute('data-v-app', '')
return proxy
}
return app
}) as CreateAppFunction<Element>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ensureRenderer方法追溯过去底添加patchclass+patchStyle等跟操作DOM相关的方法 ensureRenderer(创建虚拟DOM)一直追溯到createRenderer以及baseCreateRenderer,baseCreateRenderer方法涉及了虚拟DOM的创建更新DIFF算法
之后就是检查时候又mount是否挂载在DOM上 app对象上的方法:config、use、mixin、component、directive、mount、unmount、provide/inject
以下表格列举了现有的全局 API 与实例 API 的对应关系:
2.x 全局 API | 3.x 实例 API (应用(app)) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | 已移除 |
Vue.config.ignoredElements | app.config.isCustomElement |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
不会影响到全局行为的 API 现已作为具名 ES 模块提供给用户导入。
# 挂载应用实例
# mount
在所提供的DOM元素上挂载应用程序实例的根组件
import { createApp } from 'vue'
const app = createApp({})
// 做一些准备
app.mount('#my-app')
2
3
4
5
# unmount 新增属性
在所提供的DOM元素上卸载应用程序实例的根组件
import { createApp } from 'vue'
const app = createApp({})
// 做一些必要的准备
app.mount('#my-app')
// 应用程序将在挂载后5秒被卸载
setTimeout(() => app.unmount('#my-app'), 5000)
2
3
4
5
6
7
8
# component
//vue2.x
// 注册组件,传入一个选项对象 (自动调用 Vue.extend)
Vue.component('my-component', { /* ... */ })
// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component')
// vue3
import { createApp } from 'vue'
const app = createApp({})
// 注册组件,传入一个选项对象
app.component('my-component', {
/* ... */
})
// 获取注册的组件 (始终返回构造器)
const MyComponent = app.component('my-component', {})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# directive
注册或获取全局自定义指令
import { createApp } from 'vue'
const app = createApp({})
// 注册
app.directive('my-directive', {
// 指令的生命周期
// 在绑定元素的父组件被挂载之前调用
beforeMount(el, binding, vnode) {},
// 在挂载绑定元素的父组件时调用
mounted(el, binding, vnode) {},
// 在更新包含组件的VNode之前调用
beforeUpdate(el, binding, vnode, prevNode) {},
// 组件的VNode及其子组件的VNode更新之后调用
updated(el, binding, vnode, prevNode) {},
// 在卸载绑定元素的父组件之前调用
beforeUnmount(el, binding, vnode) {},
// 在卸载绑定元素的父组件时调用
unmounted(el, binding, vnode) {}
})
// 注册 (指令函数)
app.directive('my-directive', (el, binding, vnode, prevNode) => {
// 这里将会被 `mounted` 和 `updated` 调用
})
// getter,返回已注册的指令
const myDirective = app.directive('my-directive')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# provide/inject
该选项与inject一起使用,允许一个祖先组件作为其所有后代的依赖注入器,无论组件层次结构有多深,只要它们位于同一父链中就可以 provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。 如果在组件中两者都只能在当前活动组件实例的 setup() 中调用,详细请看依赖注入部分
import { createApp } from 'vue'
const app = createApp({
provide: {
user: 'John Doe'
}
})
app.component('user-card', {
inject: ['user'],
template: `
<div>
{{ user }}
</div>
`
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# use
常见的作者们导入加载插件的方法是,通过 Vue.use 自动加载插件的UMD版本。例如,以下展示了官方的 vue-router 插件在浏览器环境中的加载:
var inBrowser = typeof window !== 'undefined'
/* … */
if (inBrowser && window.Vue) {
window.Vue.use(VueRouter)
}
2
3
4
5
而在 Vue 3 中,use 这个全局API已经不再使用,该方法已经无法正常工作并在调用 Vue.use() 的时候会触发一个警告。取而代之的是,插件的使用者需要明确地在应用实例中声明插件的使用:
const app = createApp(MyApp)
app.use(VueRouter)
2
# mixin
optionMergeStrategies 影响,可看下方的config.optionMergeStrategies
全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用。
# config
# productionTip
config.productionTip 已移除
在Vue 3.x,提示语 “use production build” 只会在当你在使用 “dev + full build” (包含了运行时+编译器及警告的构建模式)构建应用时显示。 对于 ES 模块的构建,由于它们一般与打包工具配套使用,并且在大多数情况下 CLI 或者模版文件都会将生产环境配置好,因此该提示将不再显示。
# isCustomElement
config.ignoredElements 现改为 config.isCustomElement
引入该配置项旨在支持原生的自定义元素,所以将该选项这样重命名可以更好地表达它的作用。新的选项将接收一个更加灵活的函数以取代原先的 字符串/正则表达式 方式,如:
// 之前
- Vue.config.ignoredElements = ['my-el', /^ion-/]
// 现在
+ const app = Vue.createApp({})
app.config.isCustomElement = tag => tag.startsWith('ion-')
2
3
4
5
6
注意
在 Vue 3.0 中,检查元素是否是一个组件的过程转移到了模版编译阶段,因此该配置项只能在运行时+编译器版本中使用。当使用仅运行时版本构建应用时,isCustomElement 必须通过构建配置传递给@vue/compiler-dom,例如: 通过 vue-loader 的 compilerOptions 选项.
当使用仅运行时版本构建应用时使用了 config.isCustomElement,系统将通过一条警告信息提示用户需要构建配置传递该参数; 这将是一项新的Vue CLI的顶层配置项。
# devtools
配置是否允许 vue-devtools 检查代码。开发版本默认为 true,生产版本默认为 false。生产版本设为 true 可以启用检查。
- Vue.config.devtools = true
+ app.config.devtools = true
2
# errorHandler
- Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}
+ app.config.errorHandler = (err, vm, info) => {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 这里能发现错误
}
2
3
4
5
6
7
8
9
10
指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。 错误追踪服务 Sentry 和 Bugsnag 都通过此选项提供了官方支持。
# warnHandler
- Vue.config.warnHandler = function (msg, vm, trace) {
// `trace` 是组件的继承关系追踪
}
+ app.config.warnHandler = function(msg, vm, trace) {
// `trace` 是组件的继承关系追踪
}
2
3
4
5
6
为 Vue 的运行时警告赋予一个自定义处理函数。注意这只会在开发者环境下生效,在生产环境下它会被忽略。
# globalProperties 新增属性
app.config.globalProperties.foo = 'bar'
app.component('child-component', {
mounted() {
console.log(this.foo) // 'bar'
}
})
2
3
4
5
6
7
添加可在程序内的任何组件实例中访问的全局属性。当存在键冲突时,组件属性将优先
替代掉Vue2.x的 Vue.prototype属性放到原型上的写法
// Vue2.x
Vue.prototype.$http = () => {}
// Vue3
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}
2
3
4
5
6
# optionMergeStrategies
const app = Vue.createApp({
mounted() {
console.log(this.$options.hello)
}
})
app.config.optionMergeStrategies.hello = (parent, child, vm) => {
return `Hello, ${child}`
}
app.mixin({
hello: 'Vue'
})
2
3
4
5
6
7
8
9
10
11
12
13
定义自定义选项的合并策略。
合并策略接收在父实例options和子实例options和∗∗子实例∗∗options,分别作为第一个和第二个参数。上下文Vue实例作为第三个参数传递
【自定义选项合并策略】mixin
const app = Vue.createApp({
custom: 'hello!'
})
app.config.optionMergeStrategies.custom = (toVal, fromVal) => {
console.log(fromVal, toVal)
// => "goodbye!", undefined
// => "hello!", "goodbye!"
return fromVal || toVal
}
app.mixin({
custom: 'goodbye!',
created() {
console.log(this.$options.custom) // => "hello!"
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
optionMergeStrategies先获取到子实例的$options的mixin而没有父实例【custom第一次改变从undefined到goodbye--->打印"goodbye!", undefined】
父实例的options替换掉子实例的options替换掉子实例的options替换掉子实例的options【custom第二次从goodbye到hello!--->打印了"hello", "goodbye!"】
最后在打印app.config.optionMergeStrategies.custom返回的父实例的$options
无论如何this.options.custom最后会返回合并策略的return的值【使用场景利用父子组件的options.custom最后会返回合并策略的return的值【使用场景利用父子组件的options.custom最后会返回合并策略的return的值【使用场景利用父子组件的options,然后返回计算等操作得到所需要的值】optionMergeStrategies合并$options变化
# performance
- Vue.config.performance=true;
+ app.config.performance=true;
2
设置为 true 以在浏览器开发工具的性能/时间线面板中启用对组件初始化、编译、渲染和打补丁的性能追踪。只适用于开发模式和支持 performance.mark API 的浏览器上。