这里总结一些3.x的变更,不便查阅
1. 全局Api相干
(1) 全局api改为应用应用程序实例
import { createApp } from 'vue'
const app = createApp({})
Vue.config -> app.config
Vue.use() -> app.use // 注册插件
一些更改点:
- Vue.config.productionTip 移除
- Vue.extend 移除
// 结构器相干
// vue2.x
const Profile = Vue.extend({ // 生成组件结构器
template: 'xxx',
data() {
return {}
}
})
new Profile().$mount(dom)
// vue3.x, 移除组件结构器,改用createApp挂载
const Profile = {
template: 'xxxxx',
data() {
return {}
}
}
Vue.createApp(Profile).mount(dom)
---------------------------------
// 继承相干
3.x 应用 组合式 API 来代替继承与 mixin, 或应用extends选项代替Vue.extend
(2) 全局Api tree-shaking(webpack打包时去除无用代码,优化打包体积)
全局 API(不全局扭转行为)以及一些外部api 应用具名导出, 有利于反对tree-shaking的打包工具打包时去除未应用的全局api, 晋升性能
例如:
Vue.nextTick() -> import { nextTick } from ‘vue’
Vue.set()
2. 模板指令
(1) v-model
3.x
- v-model参数指定
- v-model替换.sync
- 绑定多个v-model
- 自定义v-model修饰符
// 2.x
// v-model 定制prop,event
// ChildComponent.vue
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
title: {
type: String,
}
}
}
<ChildComponent v-model="pageTitle" /> 等价于
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
// .sync实现双向绑定
// ChildComponent.vue
this.$emit('update:title', newValue)
<ChildComponent :title.sync="pageTitle" /> 等价于
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
-------------------
// 3.x
<ChildComponent v-model="pageTitle" />
等价于:
<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle =$event"/>
// 指定v-model参数
<ChildComponent v-model:title="pageTitle" /> 等价于
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event"/>
(2) v-for, key
3.x
- <template v-for> 的 key 应该设置在 <template> 标签上
- 条件分支不须要应用key
- v-if优先级高于v-for
(3).native修饰符
3.x 移除.native修饰符
// 2.x
<my-component
v-on:close="handleComponentEvent"
v-on:click.native="handleNativeClickEvent" // 监听原生事件
/>
// 3.x, 未被定义为子组件触发的事件,将被作为子组件的根元素的原生事件监听
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
// MyComponent
<script setup>
const emit = defineEmits(['close'])
</script>
3. 组件
(1) 函数式组件
3.x
- 只能由一般函数创立
- 移除functional选项
// 2.x
export default {
functional: true,
props: ['level'],
render(h, { props, data, children }) {
return h(`h${props.level}`, data, children)
}
}
// 3.x
import { h } from 'vue'
const DynamicHeading = (props, context) => {
return h(`h${props.level}`, context.attrs, context.slots)
}
DynamicHeading.props = ['level']
export default DynamicHeading
(2) 异步组件
应用defineAsyncComponent定义
// 2.x
const asyncModal = {
component: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}
// 3.x
const asyncModalWithOptions = defineAsyncComponent({
loader: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
(3) 在emits中申明组件须要触发的事件
因为3.x移除.native修饰符, 未被定义为子组件触发的事件,将被作为原生事件进行监听
(4) 高阶组件相干的api
3.x
- $attrs包含style、class
- $listeners移除,被整合到$attrs中(事件监听器被当作以on结尾的属性解决)
(5) 渲染函数
3.x
- render函数不承受参数,原有的h参数现改为全局引入
- 应用resolveComponent 取代字符串查找已注册的组件
// 2.x
export default {
render(h) {
return h('div')
}
}
//3.x
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
// 3.x
import { h, resolveComponent } from 'vue'
export default {
setup() {
const ButtonCounter = resolveComponent('button-counter')
return () => h(ButtonCounter)
}
}
4. 其余
(1) is attribute
限度在只能用于component标签中
// 2.x
// 应用is绕开html解析限度,被解析为<blog-post-row>组件
<table>
<tr is="blog-post-row"></tr>
</table>
// 3.x
<table>
<tr is="vue:blog-post-row"></tr>
</table>
(2) 自定义指令的钩子函数与组件得申明周期统一
const MyDirective = {
created(el, binding, vnode, prevVnode) {}, // 新增
beforeMount() {}, // 替换bind
mounted() {}, // 替换inserted
beforeUpdate() {}, // 新增
updated() {}, // 替换componentUpdated
beforeUnmount() {}, // 新增
unmounted() {}
}
(3) 对于data选项进行合并时(来自mixin/extend)应用浅合并
const Mixin = {
data() {
return {
user: {
name: 'Jack',
id: 1
}
}
}
}
const CompA = {
mixins: [Mixin],
data() {
return {
// 2.x: { user: { name: 'jack', id: 2} }
// 3.x: { user: { id: 2 } }
user: {
id: 2
}
}
}
}
(4) watch监听数组
3.x 监听数组变更必须应用deep
data() {
arr: [1, 2, 3, 4],
}
// 2.x
watch: {
arr: {
handler() {xxx},
// deep: true, //监听对象
},
},
arr = [1,2,3] // 数组替换, 触发
this.$set(arr, 0, 4) // 数组变更,触发,等价于arr.splice(0, 1, 4)
// 3.x
created() {
this.$watch('arr', () => { xxx }, { deep: true });
}
arr[1] = 4 // 数组变更
// 3.x setup语法糖
const arr = ref([])
watch(() => arr.value, () => { xxx }, { deep: true })
// 等价于
watch(arr, () => { xxx }, { deep: true })
5.移除的api
(1)过滤器
- 部分过滤器应用办法或者计算属性代替
- 全局过滤器应用全局属性代替
const app = createApp(App)
app.config.globalProperties.$filters = {
currencyUSD: (value) => '$' + value,
}
<template>
<p>{{ $filters.currencyUSD(xxxx) }}</p>
</template>
(2) Vue.set/$set, Vue.delete/$delete
(3) 移除$on,$off,$once 事件接口, 移除$children(应用$refs)
(4) 移除propsData
// 2.x
const Comp = Vue.extend({
props: ['username'],
template: '<div>{{ username }}</div>'
})
new Comp({
propsData: {
username: 'Evan'
}
})
// 3.x
const app = createApp(
{
props: ['username'],
template: '<div>{{ username }}</div>'
},
{ username: 'Evan' }
)
参考链接:
webpack之tree-shaking
vue属性透传
发表回复