VUE3官方网站:点击访问
VUE3的生命周期和VUE2的区别:点击访问
下面通过两组件和一个辅助文件说明:
<template> <div>我的父亲是{{ actionName }}</div> <div>我是非响应值{{ `${state.id},${state.attributes.name}` }}</div> <div>我是{{ name }},setValue:{{ count }}</div> <button @click="setValue">点击</button> <button @click="clickThis">给父亲带东西</button> </template> <script setup lang="ts" name="actionChild"> /** * 以define开头的api都为编译器宏 * defineExpose 这个api其实主要是解决传统vue组件过度暴露模板上的东西 * defineProps 这个api很好理解,就是定义props相关信息 * defineEmits 这个api也很好理解,就是定义emits相关信息 * PropType 注解或者是约束 defineProps(props) * nextTick 强制刷新 * ref 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value * onDeactivated * reactive 返回对象的响应式副本 * watch 响应式更改(监听值的变化然后做某些事) * onBeforeUpdate * computed * onMounted * useSlots 使用场景少 * useAttrs 使用场景少 * withDefaults 解决使用defineProps声明时无法给默认值的問题 * toRefs 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref */ import { defineExpose, defineProps, PropType, nextTick, ref, onDeactivated, reactive, watch, onBeforeUpdate, computed, onMounted, defineEmits, toRefs } from "vue"; /**声明props */ const props = defineProps({ user: { type: Object as PropType<Users> }, actionName: { type: String, } }); /** 有默认值的props声明 * const props = withDefaults(defineProps<Users>(), { * UserName: "", * Password: "你猜", * }) */ /** * ts 专有的声明,约定传递参数的类型 * const emit= defineEmits<{ * (e: 'click', num: number): void *}>() * */ /**子组件向父组件事件传递 */ const emit = defineEmits(['Handler']) const clickThis = () => { emit('Handler', { code: 1, data: "子类触发父亲方法" }) } /**声明由ref自行推导的类型 */ const count = ref(0); /**声明指定类型的ref值 */ const name = ref<string | null | number>(0); /**声明返回对象的响应式副本 (不需要通过.value 取值和赋值) */ const state = reactive({ id: 1, attributes: { name: '', } }); /**这也是可以的哦。 官方推荐使用ref定义基础类型,reactive定义复杂类型 * * const data: DataProps = reactive({ name: "zhangsan", birthYear: 2000, now: 2020, sayName: () => { console.log(1111); console.log(data.name); data.name = "I am " + data.name; console.log(data.name); }, age: computed(() => { return data.now - data.birthYear; }), }); const refData = toRefs(data) * * */ const setValue = () => { name.value = "我是响应式的name"; count.value++; } /**监听值是否发生改变 */ watch(() => props.user, (data) => { console.log("prpos 的user对象发生改变", data); }); watch(() => { if (props.user) { return null } if (props.user.UserName) { return null } return props.user.UserName; } , (data) => { console.log("prpos 的user对象的UserName发生改变", data); }); watch( () => state, (state, prevState) => { console.log('deep', state.attributes.name, prevState.attributes.name) }, { deep: true } ); /**侦听多个数据源 */ watch([count, name], (newValues, prevValues) => { console.log(newValues, prevValues) }); /**暴露指定数据,使其在父组件中使用ref可以获取其暴露的数据或者方法 */ defineExpose({ count, name, ...toRefs(state)/**通过toRefs 将非响应式的state改成响应式并导出 */ }); onMounted(() => { console.log("获取父类传入的user", props.user); console.log("获取父类传入的ActionName", props.actionName); }); </script>
<template> <div>action:{{ name }}</div> <button @click="getChildData">看一下孩子的东西</button> <button @click="setName">设置我的名称</button> <actionChildVue :ref="childRef" :action-name="name" :user="user" @handler="triggerChild" /> </template> <script setup lang="ts" name="action"> import actionChildVue from "@renderer/components/actionChild.vue";//导入子组件 import { ref, } from "vue"; const name = ref("我是父亲组件名称:动作"); /** action.d.ts 声明Users的接口类型 .d是ts中的全局声明 */ const user = ref<Users>({ UserName: 'Hello', Password: '哟,你慢慢猜' }); const triggerChild = (data) => { console.log("我孩子给我带的东西", data); } const setName = () => { name.value = "动作加1"; } const childRef = ref(null);//定义接收子组件的refs const getChildData = () => { if (childRef) { return; } console.log(childRef.value); } </script>
新建一个action.d.ts用于声明接口进行类型约束
interface Users { UserName: string | null; Password: string | null; Age?: number | null; } interface DataProps { name: string; now: number; birthYear: number; age: number; sayName: () => void; }
插件推荐:
评论区