Browse Source

feat: 函数式弹窗示例代码添加子组件`prop`为`primitive`类型的`demo` (#587)

ChasonZheng 1 year ago
parent
commit
3471e4a7e2

+ 4 - 2
src/views/components/dialog/form.vue

@@ -15,8 +15,10 @@ const props = withDefaults(defineProps<FormProps>(), {
   formInline: () => ({ user: "", region: "" })
 });
 
-// vue 规定所有的 prop 都遵循着单向绑定原则,不能在子组件中更改 prop 值,该 form.vue 文件为子组件
-// 如果需要拿到初始化的 prop 值并使得组件变量可修改,则需要在子组件定义一个新的变量接受这个子组件的 prop
+// vue 规定所有的 prop 都遵循着单向绑定原则,直接修改 prop 时,Vue 会抛出警告。此处的写法仅仅是为了消除警告。
+// 因为对一个 reactive 对象执行 ref,返回 Ref 对象的 value 值仍为传入的 reactive 对象,
+// 即 newFormInline === props.formInline 为 true,所以此处代码的实际效果,仍是直接修改 props.formInline。
+// 但该写法仅适用于 props.formInline 是一个对象类型的情况,原始类型需抛出事件
 // 推荐阅读:https://cn.vuejs.org/guide/components/props.html#one-way-data-flow
 const newFormInline = ref(props.formInline);
 </script>

+ 22 - 0
src/views/components/dialog/formPrimitive.vue

@@ -0,0 +1,22 @@
+<script setup lang="ts">
+import { useVModel } from "@vueuse/core";
+
+// 声明 props 类型
+export interface FormProps {
+  data: string;
+}
+
+// 声明 props 默认值
+// 推荐阅读:https://cn.vuejs.org/guide/typescript/composition-api.html#typing-component-props
+const props = withDefaults(defineProps<FormProps>(), {
+  data: () => ""
+});
+
+// 使用 vueuse 的双向绑定工具
+const emit = defineEmits(["update:data"]);
+const data = useVModel(props, "data", emit);
+</script>
+
+<template>
+  <el-input class="!w-[220px]" v-model="data" placeholder="请输入内容" />
+</template>

+ 31 - 2
src/views/components/dialog/index.vue

@@ -3,6 +3,7 @@ import { useRouter } from "vue-router";
 import { h, createVNode, ref } from "vue";
 import { message } from "@/utils/message";
 import forms, { type FormProps } from "./form.vue";
+import formPrimitive from "./formPrimitive.vue";
 import { cloneDeep, debounce } from "@pureadmin/utils";
 import {
   addDialog,
@@ -316,7 +317,10 @@ function onFormTwoClick() {
   addDialog({
     width: "30%",
     title: "结合Form表单(第二种方式)",
-    contentRenderer: () => h(forms, { formInline: formInline.value }),
+    contentRenderer: () =>
+      h(forms, {
+        formInline: formInline.value
+      }),
     closeCallBack: () => {
       message(
         `当前表单数据为 姓名:${formInline.value.user} 城市:${formInline.value.region}`
@@ -338,7 +342,9 @@ function onFormThreeClick() {
     width: "30%",
     title: "结合Form表单(第三种方式)",
     contentRenderer: () =>
-      createVNode(forms, { formInline: formThreeInline.value }),
+      createVNode(forms, {
+        formInline: formThreeInline.value
+      }),
     closeCallBack: () => {
       message(
         `当前表单数据为 姓名:${formThreeInline.value.user} 城市:${formThreeInline.value.region}`
@@ -373,6 +379,26 @@ function onFormFourClick() {
   });
 }
 
+// 子组件 prop 为 primitive 类型的 demo
+const formPrimitiveParam = ref("Hello World");
+const resetFormPrimitiveParam = ref(formPrimitiveParam.value);
+function onFormPrimitiveFormClick() {
+  addDialog({
+    width: "30%",
+    title: "子组件 prop 为 primitive 类型 demo",
+    contentRenderer: () =>
+      h(formPrimitive, {
+        data: formPrimitiveParam.value,
+        "onUpdate:data": val => (formPrimitiveParam.value = val)
+      }),
+    closeCallBack: () => {
+      message(`当前表单内容:${formPrimitiveParam.value}`);
+      // 重置表单数据
+      formPrimitiveParam.value = resetFormPrimitiveParam.value;
+    }
+  });
+}
+
 function onBeforeCancelClick() {
   addDialog({
     title: "点击底部取消按钮的回调",
@@ -474,6 +500,9 @@ function onBeforeSureClick() {
       <el-button @click="onFormFourClick">
         结合Form表单(第四种方式)
       </el-button>
+      <el-button @click="onFormPrimitiveFormClick">
+        子组件 prop 为 primitive 类型
+      </el-button>
     </el-space>
     <el-divider />
     <el-space wrap>