使用 Typescript 观察 Vue3 Composition API 中的 Value Prop
Watching Value Prop in Vue3 Composition API with Typescript
据我所知,基于我在网上找到的几个示例以及我相信我从 Wave 中正确理解的一般模式,我正在做的应该可以正常工作 UI的抽屉源代码。
基本上我有一个侧边栏组件,我希望它可以根据提供给它的值属性隐藏(这个想法可以根据父组件的需要、屏幕尺寸、切换按钮等进行更改) .).所以侧边栏组件有一个监视功能,它应该对 props.value
的变化做出反应
Sidebar.vue
<template>
<aside v-if="mountSidebar" class="min-h-screen">
<slot></slot>
</aside>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
export default defineComponent({
name: "Sidebar",
props: {
value: {
type: Boolean,
default: true,
},
},
setup(props) {
const mountSidebar = ref(props.value);
watch(
() => props.value,
(value) => {
mountSidebar.value = value;
}
);
return {
close,
mountSidebar,
};
},
});
</script>
然后是当前显示边栏的App.vue。
<template>
<div>
<navbar>
<dm-button rounded type="primary" @click="showSidebar = !showSidebar">Toggle Sidebar</dm-button>
Navbar Content
</navbar>
<div class="flex flex-row min-h-screen bg-gray-100 text-gray-800">
<sidebar v-model="showSidebar">
Sidebar Content
</sidebar>
<div class="flex justify-center w-full">
<router-view />
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import Navbar from "@/components/Navbar.vue";
import Sidebar from "@/components/Sidebar.vue";
import DmButton from "@/components/Button.vue";
export default defineComponent({
components: {
Navbar,
Sidebar,
DmButton,
},
setup() {
const showSidebar = ref(true);
return {
showSidebar,
};
},
});
</script>
我的 App.vue 有一个 showSidebar
布尔值引用,它在边栏组件上作为 v-model
提供。还有一个 dm-button(我写的扩展按钮组件)在点击时切换 showSidebar 的值(我知道这有效,我可以看到 App.vue 组件中的 showSidebar
值发生变化Vue 开发工具)。但是,更改不会反映在侧边栏组件中。我不确定我在这里遗漏了什么。
仅供参考,此代码已简化,删除了一些不必要的内容(例如侧边栏和导航栏中的内容)。
要将 v-model
与组件一起使用,您应该将道具命名为 modelValue
并发出一个名为 update:modelValue
的事件来改变它:
<template>
<aside v-if="modelValue" class="min-h-screen">
<slot></slot>
</aside>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
export default defineComponent({
name: "Sidebar",
props: {
modelValue: {
type: Boolean,
default: true,
},
},
emits:['update:modelValue'],
setup(props,{emit}) {
function close(){
emit('update:modelValue',false)
}
return {
close,
mountSidebar,
};
},
});
</script>
通过从 props.value
创建一个新的引用,你失去了反应性。
props
是 reactive
, so you can use toRef
or toRefs
.
const mountSidebar = toRef(props, 'value');
// or
const {value:mountSidebar} = toRefs(props);
据我所知,基于我在网上找到的几个示例以及我相信我从 Wave 中正确理解的一般模式,我正在做的应该可以正常工作 UI的抽屉源代码。
基本上我有一个侧边栏组件,我希望它可以根据提供给它的值属性隐藏(这个想法可以根据父组件的需要、屏幕尺寸、切换按钮等进行更改) .).所以侧边栏组件有一个监视功能,它应该对 props.value
的变化做出反应Sidebar.vue
<template>
<aside v-if="mountSidebar" class="min-h-screen">
<slot></slot>
</aside>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
export default defineComponent({
name: "Sidebar",
props: {
value: {
type: Boolean,
default: true,
},
},
setup(props) {
const mountSidebar = ref(props.value);
watch(
() => props.value,
(value) => {
mountSidebar.value = value;
}
);
return {
close,
mountSidebar,
};
},
});
</script>
然后是当前显示边栏的App.vue。
<template>
<div>
<navbar>
<dm-button rounded type="primary" @click="showSidebar = !showSidebar">Toggle Sidebar</dm-button>
Navbar Content
</navbar>
<div class="flex flex-row min-h-screen bg-gray-100 text-gray-800">
<sidebar v-model="showSidebar">
Sidebar Content
</sidebar>
<div class="flex justify-center w-full">
<router-view />
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import Navbar from "@/components/Navbar.vue";
import Sidebar from "@/components/Sidebar.vue";
import DmButton from "@/components/Button.vue";
export default defineComponent({
components: {
Navbar,
Sidebar,
DmButton,
},
setup() {
const showSidebar = ref(true);
return {
showSidebar,
};
},
});
</script>
我的 App.vue 有一个 showSidebar
布尔值引用,它在边栏组件上作为 v-model
提供。还有一个 dm-button(我写的扩展按钮组件)在点击时切换 showSidebar 的值(我知道这有效,我可以看到 App.vue 组件中的 showSidebar
值发生变化Vue 开发工具)。但是,更改不会反映在侧边栏组件中。我不确定我在这里遗漏了什么。
仅供参考,此代码已简化,删除了一些不必要的内容(例如侧边栏和导航栏中的内容)。
要将 v-model
与组件一起使用,您应该将道具命名为 modelValue
并发出一个名为 update:modelValue
的事件来改变它:
<template>
<aside v-if="modelValue" class="min-h-screen">
<slot></slot>
</aside>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
export default defineComponent({
name: "Sidebar",
props: {
modelValue: {
type: Boolean,
default: true,
},
},
emits:['update:modelValue'],
setup(props,{emit}) {
function close(){
emit('update:modelValue',false)
}
return {
close,
mountSidebar,
};
},
});
</script>
通过从 props.value
创建一个新的引用,你失去了反应性。
props
是 reactive
, so you can use toRef
or toRefs
.
const mountSidebar = toRef(props, 'value');
// or
const {value:mountSidebar} = toRefs(props);