赞
踩
了解vue3的setup之前,可以先回顾一下vue2.x中组件传值的写法。
// App.vue <template> <div class="app"> App <Demo name="张三" age="18" /> </div> </template> <script> import Demo from "./components/demo.vue"; export default { name: "App", components: { Demo, }, }; </script> <style> .app { width: 100%; height: 100px; background-color: beige; } </style>
// demo <template> <div class="demo">demo组件</div> </template> <script> export default { name: "demo", props: ["name", "age"], mounted() { console.log("this", this); }, }; </script> <style> .demo { width: 50%; height: 50px; background-color: pink; } </style>
通过打印this可以看到this上存在name和age
当组件中不写props时,虽然可以在
a
t
t
r
中
也
能
获
取
到
,
但
是
区
别
于
p
r
o
p
s
,
attr中也能获取到,但是区别于props,
attr中也能获取到,但是区别于props,attr中无法对传参进行类型约束,且无法在template中直接使用。
另外,当使用props接收时,$attr上是拿不到name和age。
再来看一下slot,即使没有在组件中使用slot时,会作为虚拟节点显示在 $slot中,使用后就会作为 $slot中的一个对象。
具名插槽,当组件中不接收时
以上分别演示了 $attr和 $slot写法,现在看vue3的setup
-setup的执行时机
先写一个简单的模板
// views/home.vue
<template>
<Demo></Demo>
</template>
<script>
import Demo from "@/components/demo.vue";
export default {
components: {
Demo,
},
};
</script>
// components/demo.vue <template> <p>个人信息</p> <p>姓名:{{ person.name }}</p> <p>年龄:{{ person.age }}</p> </template> <script lang="ts"> import { defineComponent, ref, reactive } from "vue"; export default defineComponent({ name: "Home", components: {}, setup() { const person = reactive({ name: "张三", age: 18, }); return { person, }; }, }); </script>
显示正常
首先代码验证setup执行时机,在beforeCrate之前,并且this是undefined。
// components/demo.vue <template> <p>个人信息</p> <p>姓名:{{ person.name }}</p> <p>年龄:{{ person.age }}</p> </template> <script lang="ts"> import { defineComponent, ref, reactive } from "vue"; export default defineComponent({ name: "Home", components: {}, beforeCreate() { console.log("---beforeCreate---"); }, setup() { console.log("---setup---"); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, }); </script>
打印后可以发现,setup执行时机是在beforeCrate之前,且this为undefined
再来看setup的参数
export default { name: "Home", setup(a, b, c) { console.log("a", a); console.log("b", b); console.log("c", c); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, };
先来第一个参数,官方定义props,为组件传值,来写一个例子并且打印
// views/home.vue
<template>
<Demo hobby="学习"></Demo>
</template>
<script>
import Demo from "@/components/demo.vue";
export default {
components: {
Demo,
},
};
</script>
// components/demo.vue <template> <p>个人信息</p> <p>姓名:{{ person.name }}</p> <p>年龄:{{ person.age }}</p> </template> <script> import { reactive } from "vue"; export default { name: "Home", setup(props) { console.log("props", props); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, }; </script>
会发现打印的内容是空的,并且有一段警告,意思是外部传递了hobby,组件内部并没有调用。
正确写法与2.x一致
// components/demo.vue <script> import { reactive } from "vue"; export default { name: "Home", props: ["hobby"], setup(props) { console.log("props", props); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, }; </script>
并且在多传参数的情况下,不会有警告
// components/demo.vue <script> import { reactive } from "vue"; export default { name: "Home", props: ["hobby", "interest"], setup(props) { console.log("props", props); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, };
正确的打印(再添加一个传值interest),可以发现props将传值整理成一个带有响应式的对象。
第二个参数叫context,可以理解成一个上下文对象
<script> import { reactive } from "vue"; export default { name: "Home", props: ["hobby", "interest"], setup(props, context) { console.log("props", props); console.log("context", context); const person = reactive({ name: "张三", age: 18, }); return { person, }; }, };
先打印一下attrs,发现并没有需要的属性
当注释掉props时,再打印attrs
与vue2.x相似,会有个警告和props的数据被attrs接收了,接着试一下事件emit和打印结果
// view/home.vue 父组件 <template> <Demo @hello="showHobby" hobby="学习" interest="还是学习"></Demo> </template> <script> import Demo from "@/components/demo.vue"; export default { components: { Demo, }, setup() { function showHobby(val) { alert(`触发hello事件,收到参数是:${val}`); } return { showHobby, }; }, }; </script>
// components/demo.vue 子组件 <template> <p>个人信息</p> <p>姓名:{{ person.name }}</p> <p>年龄:{{ person.age }}</p> <button @click="test">测试组件的hello事件</button> </template> <script> import { reactive } from "vue"; export default { name: "Home", props: ["hobby", "interest"], emits: ["hello"], setup(props, context) { console.log("props", props); // console.log("context.attrs", context.attrs); console.log("context.attrs", context.emit); const person = reactive({ name: "张三", age: 18, }); function test() { context.emit("hello", 666); } return { person, test, }; }, }; </script>
最后看一下slots
<template>
<Demo @hello="showHobby" hobby="学习" interest="还是学习">
<template v-slot:qwerb>
<span>在家</span>
</template>
</Demo>
</template>
控制台看一下打印结果
<template>
<p>个人信息</p>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>
<slot name="qwerb"></slot>
</p>
<button @click="test">测试组件的hello事件</button>
</template>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。