组件
Comp.vue
<script setup> import { ref, provide, readonly, defineAsyncComponent } from "vue"; import DemoComp from "../../components/simple/DemoComp.vue"; import ErrorComponent from "../../components/simple/ErrorComp.vue"; import LoadingComponent from "../../components/simple/LoadingComp.vue"; const count = ref(5); const isActive = ref(true); const postFontSize = ref(1); const dynamicSlotName = "slot4"; // 组件后代提供数据,避免“prop 逐级透传” provide("module_name", "ad"); const location = ref("North Pole"); function updateLocation() { location.value = "South Pole"; } //允许组件后代修改数据 provide("location", { location, updateLocation, }); //不允许组件后代修改数据 provide("read_only_count", readonly(count)); //异步组件 const HelloComp = defineAsyncComponent(() => import("../../components/simple/HelloComp.vue")); //简单用法 // 定义一个耗时执行的函数,t 表示延迟的时间, callback 表示需要执行的函数,可选 const time = (t, callback = () => { }) => { return new Promise((resolve) => { setTimeout(() => { callback(); resolve(); }, t); }); }; const Hello = defineAsyncComponent({ // 加载函数 loader: () => { return new Promise((resolve, reject) => { (async function () { await time(2000); const res = await import("../../components/simple/HelloComp.vue"); resolve(res); })(); }); }, loadingComponent: LoadingComponent, // 加载异步组件时使用的组件 delay: 1000, // 展示加载组件前的延迟时间,默认为 200ms errorComponent: ErrorComponent, // 加载失败后展示的组件 timeout: 3000, }); </script> <template> <div> <div :style="{ fontSize: postFontSize + 'rem' }"> <el-row :gutter="5"> <el-col :span="12"> <el-card class="box-card"> <template #header> <div class="card-header"> <span>组件</span> </div> </template> <demo-comp :class="{ active: isActive }" title="Vue3" greeting-message="hi" :likes="42" :is-published="false" :comments="[ { id: 234, content: 'ok' }, { id: 266, content: 'nice' }, { id: 273, content: 'not good' }, ]" :author="{ name: 'Veronica', company: 'Veridian Dynamics' }" @enlarge-text="postFontSize += 0.1">渲染default slot <template #slot2> <span>渲染slot2</span> </template> <template v-slot:slot3> <span>渲染slot3</span> </template> <template v-slot:[dynamicSlotName]> <span>渲染slot4</span> </template> <!-- 作用域插槽,父组件接收子组件传过来的值itemProps,父组件可以根据子组件传过来的值决定插槽的内容 --> <template #item="itemProps"> {{ itemProps.id + "|" + itemProps.content }} </template> </demo-comp> </el-card> </el-col> <el-col :span="12"> <el-card class="box-card"> <template #header> <div class="card-header"> <span>组件</span> </div> </template> <demo-comp :class="{ active: isActive }" title="test" greeting-message="test" :likes="30" :is-published="true" :comments="[ { id: 234, label: 'ok', num: 10 }, { id: 266, label: 'nice', num: 5 }, { id: 273, label: 'not good', num: 18 }, ]" :author="{ name: 'Veronica', company: 'Veridian Dynamics' }" @enlarge-text="postFontSize += 0.1"> <!-- 作用域插槽,父组件接收子组件传过来的值itemProps,父组件可以根据子组件传过来的值决定插槽的内容 --> <template #item="itemProps"> {{ itemProps.id + "|" + itemProps.label + "|" + itemProps.num }} </template> </demo-comp> </el-card> </el-col> </el-row> </div> <div> <p>异步组件</p> <hello-comp></hello-comp> <p>延时3s渲染</p> <hello></hello> </div> </div> </template> <style scoped> span { margin-left: 1rem; } </style>
DemoComp.vue
<script setup> import { ref, inject } from "vue"; defineOptions({ inheritAttrs: false, //禁用 Attributes 继承 }); const props = defineProps({ title: String, greetingMessage: String, likes: Number, isPublished: Boolean, author: Object, comments: Array, }); const emits = defineEmits(["enlargeText"]); const count = ref(0); // 注入上层组件提供的数据 const api_url = inject("api_url"); const module_name = inject("module_name"); const { location, updateLocation } = inject("location"); let read_only_count = inject("read_only_count"); function updateCount() { read_only_count.value++; alert("read_only_count的值为:" + read_only_count.value); } </script> <template> <div> <p :class="$attrs.class"> <span>msg:{{ title }}</span> <span>greetingMessage:{{ greetingMessage }}</span> <span>likes:{{ likes }}</span> <span>is-published:{{ isPublished ? "是" : "否" }}</span> <span>author:{{ author.name + "|" + author.company }}</span> </p> <button type="button" @click="count++">count is {{ count }}</button> <button @click="$emit('enlargeText')">Enlarge text</button> <p> <slot><span>default slot </span></slot> <slot name="slot2"><span>slot2</span></slot> <slot name="slot3"><span>slot3</span></slot> <slot name="slot4"> <span>slot4</span> </slot> </p> <!-- 作用域插槽,子组件传值item给父组件 --> <p> comments: <span v-for="(item, index) in comments" :key="index"> <slot name="item" v-bind="item"></slot> </span> </p> <p> App.vue注入: <span>{{ api_url }}</span> </p> <p> 父级组件注入(允许修改): <span>{{ module_name }}</span> <button @click="updateLocation">{{ location }}</button> </p> <p> 父级组件注入(不允许修改): <span>{{ read_only_count }}</span> <button @click="updateCount">update count</button> </p> </div> </template> <style scoped> span { margin-left: 1rem; } button, a { border: 1px solid blue; margin-left: 1rem; } </style>
标签:count,vue,const,..,学习,only,vue3,组件 From: https://www.cnblogs.com/caroline2016/p/17928314.html