这是我参与「第五届青训营 」笔记创作活动的第6天
- ref 系列
- ref 和 reactive 的区别
- ref 支持所有类型,reactive 只支持引用类型,如 Array Object Map Set 等等
- ref 取值赋值都需要在变量名后面加上 .value , reactive 不需要
- reactive 是 proxy 包装的,不可以直接赋值,否则会破坏响应型对象的
- 解决方案:数组可以通过push
let list = reactive<string[]>([]) let res = ['a','b','c'] list.push(...res)
- 解决方案:也可以直接将 list 包装成 Object
- 解决方案:数组可以通过push
- ref 和 reactive 的区别
- to 系列
- toRef ---> 这样一来的话,修改 like 的时候,就会同步修改 age
const man = reactive({name: 'abc', age: 23}) const like = toRef(man, 'age')
- 应用场景:比如说你拿到一个对象,但是只用其中某个属性,就可以这样直接提出来
- toRefs
- 应用场景:解构赋值
- toRaw ---> 将响应式代理对象还原成普通对象
- toRef ---> 这样一来的话,修改 like 的时候,就会同步修改 age
- 特殊情况
- computed 的
- watch
- watch 可以监听响应式数据
watch(msg, (newVal, oldVal) => { //...... }) watch([msg1, msg2], (newVal, oldVal) => { //......这里的 newVal 和 oldVal 是数组 })
- 监听对象的某一个属性,需要调用回调函数,比如
() => msg.content
watch(() => msg.content, (newVal, oldVal) => { //...... })
- 相关配置
- 深度监听
deep
watch(msg, (newVal, oldVal) => { //...... }, {deep: true})
- 对于 ref 开启深度监听 newVal 和 oldVal 长得一样
- 对于 reactive 不需要开启深度监听
- 立即执行
immediate
——立即执行一次 flush
flush = 'pre'
flush = 'sync'
flush = 'post'
- 深度监听
- watch 可以监听响应式数据
- 父子组件通信
- 子组件接受父组件
- 父向子传输
<template> <A :title='name' :arr='list'></A> </template> <script setup lang='ts'> import A from './components/A.vue' let name = 'vychod'; let list = [1,2,3]; </script>
- setup 中声明
// typescript vue3 // ts 特有定义默认设置值 withDefaults(a,b) 把 a 的默认值设置为 b withDefaults(defineProps<{ // 设置数据类型 title: String, arr: number[] }>(), { // 设置默认值 title: () => 'blog', arr: () => [666] })
↑ 这个地方该怎么在ts中访问到这个
title
和arr
呢,是不是可以直接使用呀 → 不可以。也必须要使用 props.title,同下面 ↓// javascript vue2 const props = defineProps({ title: { type: String, default: '默认值' }, arr: { type: Array, default: [] }, }); console.log(props.title); // 在 template 中使用的时候可以直接用 title,但是在 setup 中使用的时候需要使用 props.title
- template 直接通过
title
arr
这样子的命名使用即可
- 父向子传输
- 子组件向父组件通信
- 向父组件直接发送信号
// 子组件中 <template> <button @click='send'>给父组件传值</button> </template> <script setup lang='ts'> const emit = defineEmits(['on-click']) // ts 的另一种写法 // const emit = defineEmits<{ // (e: "on-click", name: String, age: Number):void, // (e: "on-click2", name: String, ):void, // (e: "on-click3", name: String, ):void // }>() const send = () => { emit('on-click', 'vychod', 24) } </script> // 父组件中 <template> <A @on-click='getInfo'></A> </template> <script setup lang='ts'> import A from './components/A.vue' const getInfo = (name:String, age:Number) => { console.log(name, age); } </script>
- 向父组件暴露属性
// 父组件中 <template> <A ref="Aref"></A> </template> <script setup lang='ts'> import { ref, reactive, onMounted } from 'vue' import A from './components/A.vue' const Aref = ref<InstanceType<typeof A>>() onMounted(()=>{ console.log(Aref.value?.name) }) </script> // 子组件中 <template> 这是A组件 </template> <script setup lang='ts'> defineExpose({ name: 'vychod', open: () => { console.log(123) } }) </script>
感觉就像是 前者是主动的,我想要让父组件知道,后者是被动的,我把属性广播出来了,你爱看不看
- 子组件接受父组件