1.0.0 • Published 23 days ago
options2composition v1.0.0
Options API to Composition API
迁移指南
官方迁移支持文档: https://v3-migration.vuejs.org/zh/
开发
使用gogocode进行开发注意: 目前发现添加注释失败、scope.rename无法正确重命名import解构的变量,
注意事项
<script setup>
不会暴露任组件的内容任何的声明, 当使用模版引用调用组件方法或获取数据时,需要开发者手动定义组件可暴露的声明。(详见 https://cn.vuejs.org/api/sfc-script-setup.html#defineexpose)- 无法识别动态内容,需开发者手动处理,例如:
this[type]
、this[funcName]()
、this.$emit(eventName)
todo list
- name
- components
- 组件名属性简写
{ comC, }
- 支持属性定义组件别名
{ comAlisa: comA, }
- 动态组件
{ comD: () => import('xxxxxx'), }
- 组件名属性简写
- props
- 对象声明
{ props: { propA: { type: String, ...其他属性 } } }
- 数组声明
{ props: ['propA']
- 对象声明
- data
- 简单函数声明(函数内只有return 对象字面量语句形式)
{ data() { return { name: 1 } } }
- 较复杂函数声明(函数内有其他非return 语句)
{ data() { const name = 1; return { name } } }
- 对象字面量声明Data
{ data: { name: 1 } }
(暂不考虑支持,此为不推荐的使用方式) - 引入变量声明data
{ data: compData }
(暂不考虑支持,此为不推荐的使用方式)
- 简单函数声明(函数内只有return 对象字面量语句形式)
- computed
- computed函数
- 支持使用vuex的mapState、mapGetters,
{ ...mapState(), ...mapGetters() }
- watch
- 支持监听route以及route属性
{ route() {} }
、'router.path'(){ }
- 支持对象配置
{ dataA: { handler(){}, deep: true, immediate: true } }
- 支持监听route以及route属性
- directives
- event
- $emit
- $on 暂不支持
- $once 暂不支持
- $off 暂不支持
- eventBus
const eventBus = new Vue();
- provide 暂不支持
- inject 暂不支持
- inheritAttrs 暂不支持
- model 暂不支持
- lifeCycle
- beforeCreate
- created
- beforeMount
- mounted
- activated
- deactivated
- beforeUpdate
- updated
- beforeDestroy
- destroyed
- errorCaptured
- renderTracked, vue3 options api选项,顺手支持了
- renderTriggered, vue3 options api选项,顺手支持了
this.$nextTick
this.$mount
(暂不考虑支持,非常见用法)this.$forceUpdate
(暂不考虑支持,非常见用法)this.$destroy
(暂不考虑支持,非常见用法)
- methods、filters
- 变量引用
{ funA: funB }
或{ funA: funA }
或{ funA }
- 语句
{ funA: debounce(function () { ...doSomething }) }
- 函数声明
{ funA() {} }
或funA: function () {}
等 - 支持vuex的mapActions,
{ ...mapActions() }
- 变量引用
- this引用
- this引用data属性
- this引用props
- this引用methods或filters
- 支持
this.$route
- 支持
this.$router
this.$set
this.$delete
this.$el
=> $vm.&elthis.$refs
=> $vm.$refsthis.$attrs
this.$data
this.$props
this.$listeners
this.$options
this.$root
this.$slots
this.$scopedSlots
this.$parent
this.$children
vue3已移除该属性, https://v3-migration.vuejs.org/zh/breaking-changes/children.html#%E6%A6%82%E8%A7%88this.$watch
- 解构this
const { title } = this
- this重命名
const self = this
- 其他未知的this语句, 转化为$vm语句
this.propertyA
转化为$vm.propertyA
不支持转换的属性
- mixins
name
option
export default {
name: 'EName'
}
composition
import { defineExpose } from 'vue';
defineExpose({
name: 'EName',
});
components
option
import componentA from '@/xxx/xxx/componentA.vue';
import componentB from '@/xxx/xxx/componentB.vue';
export default {
components: {
componentA,
componentAlisa: componentB
}
}
composition
import componentA from '@/xxx/xxx/componentA.vue';
import componentB as componentAlisa from '@/xxx/xxx/componentB.vue';
mixins(不支持)
props
option
export default {
props: {
userName: String,
userAge: [String, Number],
userInfo: {
type: Object,
required: false,
default: () => ({
userName: 'Todd Cochran',
userAge: 20
})
}
}
}
composition
const props = defineProps({
userName: String,
userAge: [String, Number],
userInfo: {
type: Object,
required: false,
default: () => ({
userName: 'Todd Cochran',
userAge: 20
})
}
})
data
data() {
return {
firstName: '',
lastName: '',
age: this.userAge || 20,
birthday: new Date().getFullYear(),
married: false,
child: null,
address: undefined,
experience: {},
friends: ['Casey Adams', 'Lena Clark', 'Nzinga Blake']
}
},
import { ref, reactive } from 'vue'
const firstName = ref('')
const lastName = ref('')
const age = ref('')
const birthday = ref(new Date().getFullYear())
const married = ref(false)
const child = ref(null)
const address = ref(undefined)
const experience = reactive({})
const friends = reactive([])
computed
export default {
computed: {
friendNames() {
return this.friends.join(', ')
},
fullName: {
get: () => {
return this.firstName + ' ' + this.lastName
},
set: (newValue) => {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
}
const friendNames = computed(() => {
return data.friends.join(', ')
})
const fullName = computed({
get: () => {
return data.firstName + ' ' + data.lastName
},
set: (newValue) => {
const names = newValue.split(' ')
data.firstName = names[0]
data.lastName = names[names.length - 1]
}
})
filter
export default {
filters: {
toMarried(value) {
return value ? 'Yes' : 'No'
}
},
}
function toMarried(value) {
return value ? 'Yes' : 'No'
}
watch
export default {
watch: {
userName(nVal, oVal) {
console.log('watch props', nVal, oVal)
},
firstName(nVal, oVal) {
console.log('watch data', nVal, oVal)
},
friendNames(nVal, oVal) {
console.log('watch computed', nVal, oVal)
},
lastName: {
handler(nVal, oVal) {
console.log('watch options', nVal, oVal)
},
immediate: false,
deep: true
}
},
}
watch(() => props.userName, (nVal, oVal) => {
console.log('watch props', nVal, oVal)
})
watch(() => data.firstName, (nVal, oVal) => {
console.log('watch data', nVal, oVal)
})
watch(() => friendNames.value, (nVal, oVal) => {
console.log('watch computed', nVal, oVal)
})
watch(() => data.lastName, (nVal, oVal) => {
console.log('watch options', nVal, oVal)
}, {
immediate: false,
deep: true
})
methods
export default {
methods: {
async getData() {
console.log('async function')
},
onSubmit(value0, { value1, value2 }) {
console.log('function arguments', value0, value1, value2)
},
vmMethods() {
this.$nextTick(() => {
this.$set(this.experience, '2020', 'principle of compiling')
this.$delete(this.experience, '2019')
this.$emit('change-val', +new Date())
this.$refs.childenComponent.name
this.$attrs.name
this.$slots.name
this.$route.name
this.$router.push({ name: 'Home' })
this.$store.state.name
})
},
otherMethods() {
this.$data
this.$props
this.$el
this.$options
this.$parent
this.$root
this.$children
this.$isServer
this.$listeners
this.$watch
this.$on
this.$once
this.$off
this.$mount
this.$forceUpdate
this.$destroy
}
}
}
const { proxy: $vm } = getCurrentInstance()
async function getData() {
console.log('async function')
}
function onSubmit(value0, { value1, value2 }) {
console.log('function arguments', value0, value1, value2)
}
function vmMethods() {
nextTick(() => {
set(data.experience, '2020', 'principle of compiling')
delete(data.experience, '2019')
emit('change-val', +new Date())
childenComponent.value.name
attrs.name
slots.name
route.name
router.push({ name: 'Home' })
store.state.name
})
}
function otherMethods() {
$vm.$data
$vm.$props
$vm.$el
$vm.$options
$vm.$parent
$vm.$root
$vm.$children
$vm.$isServer
$vm.$listeners
$vm.$watch
$vm.$on
$vm.$once
$vm.$off
$vm.$mount
$vm.$forceUpdate
$vm.$destroy
}
生命周期
export default {
async created() {
console.log('created async function')
},
mounted() {
console.log('mounted function')
},
updated() {
console.log('updated function')
},
destroyed() {
console.log('destroyed function')
},
activated() {
console.log('activated function')
},
deactivated() {
console.log('deactivated function')
},
errorCaptured(err, vm, info) {
console.log('errorCaptured function', err, vm, info)
},
}
async function onCreated() {
console.log('created async function')
}
onCreated()
onMounted(() => {
console.log('mounted function')
})
onUpdated(() => {
console.log('updated function')
})
onUnmounted(() => {
console.log('destroyed function')
})
onActivated(() => {
console.log('activated function')
})
onDeactivated(() => {
console.log('deactivated function')
})
onErrorCaptured((err, vm, info) => {
console.log('errorCaptured function', err, vm, info)
})
1.0.0
23 days ago