1、自定义组件,并使用 v-model 进行数据双向绑定。
简述: 自定义组件使用 v-model
进行传参时,遵循 Vue 3 的 v-model
机制。在 Vue 3 中,v-model
默认使用了 modelValue
作为 prop
名称,以及 update:modelValue
作为事件名称。
例子:
首先,我们创建一个自定义组件 MyInput.vue,该组件使用 <script setup>
语法,并允许通过 v-model
绑定值:
<!-- MyInput.vue -->
<template> <input :value="modelValue" @input="updateValue" />
</template> <script setup>
import { defineProps, defineEmits, ref } from 'vue'; const props = defineProps({ modelValue: String
}); const emit = defineEmits(['update:modelValue']); const updateValue = (event) => { emit('update:modelValue', event.target.value);
};
</script>
在这个例子中,使用了 defineProps
来定义 modelValue prop
,它对应于 v-model
绑定的值。同时,我们使用 defineEmits
来声明 update:modelValue
事件,该事件将在输入框的值变化时被触发。
接下来,在父组件中使用这个自定义组件,并通过 v-model
绑定一个数据属性:
<!-- ParentComponent.vue -->
<template> <div> <p>Value in Parent: {{ inputValue }}</p> <MyInput v-model="inputValue" /> </div>
</template> <script setup>
import { ref } from 'vue';
import MyInput from './MyInput.vue'; const inputValue = ref('');
</script>
在父组件中,导入了自定义的 MyInput
组件,并使用 v-model
将 inputValue
绑定到该组件的 modelValue prop
上。当 MyInput
组件中的输入框值变化时,它会触发 update:modelValue
事件,进而更新父组件中的 inputValue
。
注意,在 <script setup>
中,不需要显式地返回任何东西给模板,因为所有的响应式状态(通过 ref
或 reactive
创建)和函数都会自动暴露给模板。这使得代码更加简洁和直观。
2、异步加载动态组件
├─ src │ ├─ components │ │ ├─ ChartA.vue │ │ ├─ ChartB.vue │ │ └─ ChartC.vue │ └─ test-async.vue └─ package.json
异步加载组件
方式一:
<template><AsyncOne />
</template><script setup>
import { defineAsyncComponent } from "vue";const AsyncOne = defineAsyncComponent(() =>import("@/components/ChartA.vue")
);
</script>
方法二:vue3+vite5 中
<template><AsyncTwo/>
</template><script setup>
import { defineAsyncComponent, ref } from "vue";const AsyncTwo = ref(null);
AsyncTwo.value = registerComponent("/ChartC");// 使用异步组件的方式加载组件
const registerComponent = (componentPath) => {const modules = import.meta.glob("./components/**/*.{vue,tsx}");for (const item in modules) {if (item.includes(componentPath)) {return defineAsyncComponent(modules[item]);}}
};
</script>
异步加载动态组件
<template><div v-for="(item, index) in componentsInfo" :key="index"><component :is="item.loadComp" /></div>
</template><script setup>
import { defineAsyncComponent, onMounted, ref } from "vue";const componentsInfo = ref([{id: "1-1",title: "图表A",component: "/ChartA",},{id: "1-2",title: "图表B",component: "/ChartB",},{id: "1-3",title: "图表C",component: "/ChartC",},
]);onMounted(() => {processLoad(componentsInfo.value);
});const processLoad = (info) => {for (let i = 0; i < info.length; i++) {let item = info[i];if (!item.component) {continue;}let resComp = registerComponent(item.component);item.loadComp = resComp;}
};// 注册一个异步组件
const registerComponent = (componentPath) => {//获取 src/components 文件夹下所有组件const modules = import.meta.glob("./components/**/*.{vue,tsx}"); for (const item in modules) {if (item.includes(componentPath)) {return defineAsyncComponent(modules[item]);}}
};
</script>
效果: