使用 Typescript 在 Vue3 组合 API 中观察 Value Prop
Posted
技术标签:
【中文标题】使用 Typescript 在 Vue3 组合 API 中观察 Value Prop【英文标题】:Watching Value Prop in Vue3 Composition API with Typescript 【发布时间】:2021-07-30 19:30:43 【问题描述】:据我所知,根据我在网上找到的几个示例以及我相信我从 Wave UI 的抽屉式源代码中正确理解的一般模式,我正在做的事情应该可以正常工作。
基本上我有一个侧边栏组件,我希望它可以根据提供给它的 value 属性隐藏(想法是它可以根据父组件的需要、屏幕大小、切换按钮等进行更改) .所以侧边栏组件上有一个监视功能,它应该对 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 按钮(我编写的扩展按钮组件)在单击时切换 showSidebar 的值(我知道这是可行的,我可以在 Vue Devtools 的 App.vue 组件中看到 showSidebar
值发生变化)。但是,更改不会反映在侧边栏组件中。我不确定我在这里缺少什么。
仅供参考,此代码已简化为删除了一些不必要的内容(例如侧边栏和导航栏内的内容)。
【问题讨论】:
【参考方案1】:要将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>
【讨论】:
我想我只是不明白孩子需要发射部分来监听 v-model 的变化,我认为这只是为了让父母可以监听发射并进行调整如果子组件也有办法改变它自己的状态,父组件需要知道它的状态。名称 modelValue 重要还是只是为了清楚起见?【参考方案2】:通过从 props.value
创建一个新的 ref,你失去了反应性。
props
是reactive
,所以你可以使用toRef
或toRefs
。
const mountSidebar = toRef(props, 'value');
// or
const value:mountSidebar = toRefs(props);
【讨论】:
mountSidebar
并不意味着反应,它只是从道具中获取其初始值。最终会有一些逻辑,以便在更新 v-model 时启动过渡动画,这将手动改变 mountSidebar 以及可能我尚未编码的另一个值。 @BoussadjraBrahim 的解决方案解决了我的问题。以上是关于使用 Typescript 在 Vue3 组合 API 中观察 Value Prop的主要内容,如果未能解决你的问题,请参考以下文章
Vite2+Vue3+TypeScript:搭建企业级轻量框架实践