共计 6516 个字符,预计需要花费 17 分钟才能阅读完成。
1. 组件引入
当使用 setup
的时候,组件直接引入就可以了,不需要再自己手动注册
2. ref 和 reactive
ref
一般用于基本的数据类型,比如 string
,boolean
,reactive
一般用于对象 ref 的地方其实也是调用的 reactive
实现的。
{{title}}
{{data}}
3. defineEmits 和 defineProps 获取父组件传过来值和事件
// 第一种不带默认值 props
const props = defineProps()
// 第二种带默认值 props
export interface ChildProps {
foo: string
bar?: number
}
const props = withDefaults(defineProps(), {
foo: "1qsd"
bar?: 3
})
// 第一种获取事件
const emit = defineEmits()
// 第二种获取事件
const emit = defineEmits(["dosth"])
4. 使用 useAttrs 和 useSlots
useAttrs
可以获取父组件传过来的 id
、class
等值。useSlots
可以获得插槽的内容。例子中,我们使用 useAttrs
获取父组件传过来的 id
、class
、useSlots
获取插槽的内容。
父组件:
{{fatherRef}}
1223
子组件:
11
使用自定义指令
在 setup
里边自定义指令的时候,只需要遵循vNameOfDirective
这样的命名规范就可以了
比如如下自定义 focus
指令,命名就是 vMyFocus
,使用的就是 v-my-focus
自定义指令
5. 使用 defineExpose 子组件传父组件
子组件
父组件
222
6. 父组件传子组件
父组件
子组件
2222
7. toRefs
当从父组件向子组件传 props
的时候,必须使用 toRefs
或者 toRef
进行转一下,这是为什么呢?
这里是因为如果不使用 toRefs
转一次的话,当父组件中的 props
改变的时候,子组件如果使用了 Es6 的解析,会失去响应性。
可以看下如下例子
父组件
{{fatherRef}}
子组件
{{fatherRef}}
可以看到当父组件如果点击之后,因为使用 const {fatherRef} = props;
进行解析,就失去了响应性
所以当父组件变成 2 的时候,子组件还是 1。
这里有两种解决办法
-
使用
const {fatherRef} = toRefs(props)
; -
在模版中中使用
props.fatherRef
8. 子组件使用 v-model
8.1 可以在子组件中使用 computed,实现双向绑定
父组件
{{fatherRef}}
子组件
8.2 可以从父组件传递值和改变值的方法,然后子组件也可以使用 v-model
例子中父组件传递 modelValue
和 update:modelValue
方法 父组件:
子组件:
9. 递归组件
组件本身是可以调用组件自身的,也就是递归。vue3 中使用文件名称自动注册为组件的名称,比如名为 Child.vue
的组件可以在其模板中用
引用它自己。 这里需要注意的是需要设置条件语句,用来中断递归,不然递归会无限递归下去。
父组件
子组件
2"
>
10. vue3 ts 获取组件 ref 实例
通过对 div 元素 添加了 ref 属性,为了获取到这个元素,我们声明了一个与 ref 属性名称相同的变量sectionRef,然后我们通过 sectionRef.value 的形式即可获取该 div 元素
{{item}}
通过对父元素添加了 ref 属性,并声明了一个与 ref 属性名称相同的变量 listRef,此时通过 listRef.value 会获得包含子元素的 dom 对象 此时可以通过 listRef.value.children[index]
的形式获取子元素 dom
-
通过:ref 将 dom 引用放到数组中
{{item}}通过:ref 循环调用
setRefAction
方法,该方法会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素 此时可以通过state.refList[index]
的形式获取子元素 dom -
通过子组件emit 传递 ref
{{item}}
通过对子组件添加了 ref 属性,并声明了一个与 ref 属性名称相同的变量 cellRef,此时可以通过emit 将 cellRef.value 作为一个 dom 引用传递出去
import {defineComponent, ref, onMounted} from "@vue/runtime-core";
import {ElForm} from "element-plus";
export default defineComponent({setup() {const $form = ref>(null);
onMounted(() => {$form.value?.validate; // 类型正确});
return () => ;
},
});
需要注意的是,如果使用 expose 暴露方法出去,无法获取到对应的类型,您需要自定义类型 github.com/vuejs/rfcs/…[1]
// 组件 MyForm
import {defineComponent, ref, onMounted} from "@vue/runtime-core";
import {ElForm} from "element-plus";
type ELEForm = InstanceType;
// 在外界通过 ref 获取组件实例 请使用这个类型
export interface MyFormExpose {validate: ELEForm["validate"];
}
export default defineComponent({
name: "MyForm",
setup(props, { expose}) {const $form = ref>(null);
expose({validate: (callback) => $form.value?.validate(callback),
} as MyFormExpose);
return () => ;
},
});
原文地址: Vue3 setup TypeScript: 构建现代、类型安全的 Vue 应用的关键技巧总结