vue3 语法会比vue2 简洁
这里通过一个点击按钮累加的列子,来对比vue2和vue3的语法
vue2
<template>
<button @click="add">{{ count }}</button>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
methods: {
add() {
this.count++;
},
},
};
</script>
<style scoped></style>
vue3
<template>
<button @click="add">{{ count }}</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
const add = () => {
count.value++;
};
</script>
<style scoped></style>
从这里看出来,vue3的语法比vue2简洁很多,配和setup语法糖,代码更加简洁,结构更加清晰,速度更快
这里讲解一下案例里的ref,顺带引出 reactive
reactive
- reactive 是vue3的响应式数据,它接受一个对象,返回一个响应式对象,这个对象里的数据,当数据发生改变时,视图会自动更新 2,reactive 只能接受对象,不能接受数组和普通变量
ref
- ref 是vue3的响应式数据,它接受一个值,返回一个响应式对象,这个对象里的数据,当数据发生改变时,视图会自动更新 2,ref 可以接受数组和普通变量 3,ref 的值需要通过 .value 来访问和修改
- 日常中推荐全部使用 ref,因为 ref 可以接受数组和普通变量,而 reactive 只能接受对象
计算属性 computed
语法格式
const computedlist = computed(() => {
return count.value;
});
- computed主要是用来计算属性的,它接受一个函数,返回一个计算后的值
- 通过声明一个变量来存储计算后的值:computedlist,方法里通过return 返回计算后的值,
- 注意:这里的值如果是ref创建的需要通过 .value 来访问和修改
侦听器 watch
语法格式
监听一个数据
watch(count, (newVal, oldVal) => {
console.log(newVal, oldVal);
});
- watch 是用来监听数据的,它接受两个参数,第一个参数是你要监听的数据,可以是ref创建的,也可以是reactive创建的,也可以是普通变量
- 第二个参数是回调函数,当监听的数据发生改变时,会触发回调函数,回调函数有两个参数,第一个参数是新的值,第二个参数是旧的值
- 注意:这里的值如果是ref创建的需要通过 .value 来访问和修改
监听一个对象
# 监听一个数据,并且深度监听
watch(count, (newVal, oldVal) => {
console.log(newVal, oldVal);
}, { deep: true })
- 深度监听:当监听的数据是用ref创建时,需要设置 deep 为 true,才能监听到对象里的属性的变化
监听多个数据
watch([count, count2], (newVal, oldVal) => {
console.log(newVal, oldVal);
});
- watch 可以监听多个数据,它接受一个数组,数组里的每个元素都是你要监听的数据,也可以把多个数据存储在一个数组里,然后一起监听
- 回调函数的参数是一个数组,数组里的每个元素都是对应的数据的新值和旧值
- 注意:这里的值如果是ref创建的需要通过 .value 来访问和修改
生命周期
Vue3 的生命周期 API 对应表
| 选项式 API | 组合式 API |
|---|---|
| beforeCreate / created | setup() |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
生命周期是按照顺序执行的
父子通信
父传子
- 父组件导入子组件,在子组件上绑定属性
- 子组件通过defineProps 接收父组件传递的属性,并生命类型,比如:name: string
父组件代码
<template>
<sun message="hello sun"/>
</template>
<script setup>
import { ref, reactive, computed } from "vue";
import sun from "./components/sun.vue";
</script>
<style scoped></style>
子组件代码
<template>
{{ message }}
</template>
<script setup>
const props = defineProps({
message: String
})
</script>
<style scoped></style>
子传父
- 父组件导入子组件,在子组件上绑定事件
- 子组件通过defineEmits 接收父组件传递的事件,并声明类型,比如:message: String
- 子组件通过emit 触发事件,并传递参数,比如:emit(‘message’, ‘hello father’)
父组件代码
<template>
<div>
<p>收到子组件:{{ msg }}</p>
<sun @sendMsg="msg = $event"/>
</div>
</template>
<script setup>
import { ref } from 'vue'
import sun from './components/sun.vue'
const msg = ref()
</script>
<style scoped></style>
子组件代码
<template>
<button @click="send">返回子组件数据</button>
</template>
<script setup>
const emit = defineEmits(['sendMsg'])
const send = () => {
emit('sendMsg', '我是子组件的数据')
}
</script>
模版引用
通过 ref 标识获取真实的 dom 对象或者组件实例对象
- 创建一个ref对象
- 在标签里绑定ref对象
- 组件挂载完毕才可以获取
<template>
<div ref="divref">123</div>
</template>
<script setup>
import { ref, onMounted} from 'vue'
const divref = ref(null)
onMounted(() => {
console.log(divref.value)
})
</script>
<style scoped></style>
顶层到底层的数据传递
通过 provide 和 inject 实现数据的传递
- 在顶层组件里通过 provide 提供数据
- 在子组件里通过 inject 接收数据
顶层代码
<template>
<div>
<p>收到子组件:{{ msg }}</p>
<sun @sendMsg="msg = $event"/>
</div>
</template>
<script setup>
import { ref, provide} from 'vue'
const msg = ref()
provide('msg', msg)
</script>
<style scoped></style>
底层代码
<template>
</template>
<script setup>
import { ref, inject} from 'vue'
const msg = inject('msg')
</script>