最近在尝试使用vue3,整理了一些和vue2在使用上的一些区别
1. 代码结构变化
1.1 vue2
的script
结构
<template>
<div>
</div>
</template>
<script>
export default {
name: '',
components: {},
props: {},
data() {
return {}
},
watch: {},
created() {},
mounted() {},
methods: {}
}
</script>
<style lang="scss" scoped></style>
1.2 vue3
的script
结构
<template> </template>
<script lang="ts">
import { defineComponent, onMounted, reactive, UnwrapRef, watch } from 'vue';
interface State {}
export default defineComponent({
name: 'components name',
props: {},
setup(props) {
console.log('props: ', props);
//data
const state: UnwrapRef<State> = reactive({});
//Lifecycle Hooks
onMounted(() => {});
//watch
watch(
() => props,
(_count, _prevCount) => {},
{
deep: true,
immediate: true,
}
);
//methods
const getList = () => {};
return {
state,
getList
};
},
});
</script>
<style lang="scss" scoped></style>
下表包含如何在 setup ()
内部调用生命周期钩子:
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
2. 变量的声明与赋值
//import { ref } from 'vue';
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
变量的声明有点类似于react
的State Hook
3. 对象/数组的声明与赋值(响应性)
推荐使用reactive包裹数组,
//import { reactive } from 'vue';
const state = reactive({
arr: []
});
state.arr = [1, 2, 3]
或者
const state = ref([])
state.value = [1, 2, 3]
或者
const arr = reactive([])
arr.push(...[1, 2, 3])
这几种办法都可以触发响应性,然后界面中正常使用v-for
即可,推荐第一种
4. props/$emit
父子组件传值的写法
- 父组件
<Search @searchData="searchData" :quaryParams="quaryParams"/>
父组件的写法和vue
还是一样的,只是子组件需要作一些改变
- 子组件
<script lang="ts">
import { defineComponent } from 'vue';
interface GetUserListParams {
pageNum: number;
pageSize: number;
roleName: string;
}
export default defineComponent({
name: 'Search',
props: {
quaryParams: {
type: Object as PropType<GetUserListParams> ,
default: () = > ({
pageNum: 1,
pageSize: 10,
roleName: ''
})
}
},
emits: ['searchData'],//需要声明emits
setup(_props, context) {
const onSubmit = () => {
context.emit('searchData', "我是子节点传递给父节点的值");
}
return {
getData
}
}
});
</script>
5. Provide / Inject
5.1 vue2
写法
- 父组件
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
provide: {
location: 'North Pole',
geolocation: {
longitude: 90,
latitude: 135
}
}
}
</script>
- 子组件
<!-- src/components/MyMarker.vue -->
<script>
export default {
inject: ['location', 'geolocation']
}
</script>
5.2 vue3
写法
- 父组件
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
}
}
</script>
- 子组件
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
更多可阅读Provide / Inject
6. watch
- vue2
watch: {
count: {
handler: function(val, oldval) {},
immediate: true,
deep: true
}
}
- vue3
setup() {
const count = ref(0)
//监听count
watch(
() = > count, (_count, _prevCount) = > {}, {
deep: true,
immediate: true
}
);
}
7.重置数据
在vue2里我们可以使用this.$options.data.xxx
来重置某个数据的初始值
vue3目前只探索出只有这个可以用
setup() {
const initialState = {
name: "",
lastName: "",
email: ""
};
const form = reactive({ ...initialState });
function resetForm() {
Object.assign(form, initialState);
}
return { form, resetForm };
}
8.获取$.XXX
比如$forceUpdate
迫使组件实例重新渲染
<template>
<div>
<div>{{arr}}</div>
<button @click="handleClick">add</button>
</div>
</template>
<script lang="ts">
import { defineComponent, getCurrentInstance } from "vue";
export default defineComponent({
setup() {
const { ctx: _this }: any = getCurrentInstance()
let arr = [1]
const handleClick = () => {
arr.push(2)
_this.$forceUpdate()
}
return {
arr
};
},
});
</script>
9.定义全局变量
以axios为例
vue2
import axios from 'axios'
Vue.prototype.$axios = axios
使用this.$axios.xxx
vue3-global-api
import axios from 'axios';
const app = Vue.createApp(App);
app.config.globalProperties.$axios = axios;
使用this.$axios.xxx
vue3-provide/inject
Provide
import axios from 'axios';
const app = Vue.createApp(App);
app.provide('$axios', axios);
Inject
Composition API:
const { inject } = Vue;
...
setup() {
const $axios = inject('$axios');
// $axios.get(...)
}
Options API:
inject: ['$axios'],