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;
}插件推荐:

评论区