【vue】展示组件设计

9/14/2024 vue

对于我们后端开发的同学,总会接触到一些管理系统前端开发任务,当开发表单页面时,通常会将业务和表单控制相关的界面逻辑混合在一起,导致维护困难。

# 展示组件

顾明思议,展示组件只是用来展示数据的,组件内不会涉及一些业务操作,只涉及业务流程控制,并且在双向绑定时业务确保数据流是单向流通的。

# 展示组件 TestComponent

<script setup>
  import {watch} from "vue";

  const props = defineProps({
    domain: {
      type: Object,
      default: () => ({
        username: '',
        gender: 1,
        tags: [],
        other: {
          school: [],
          work: {
            exp1: '',
            exp2: '',
          }
        },
      })
    }
  })

  // 深度监控数据变化,提交修改事件
  watch(() => props.domain, (n, o) => {
    console.log('传递参数改变了')
    emits('change', n)
  }, {deep: true})

  const emits = defineEmits(['submit', 'change'])

  // 提交 提交事件
  const onClick = (e) => {
    e.preventDefault();
    emits('submit', props.domain)
  }
</script>

<template>
  <div class="test-component">
    <form>
      <div class="form-item">
        <label for="username">用户名</label>
        <input type="text" id="username" name="username" v-model="domain.username" class="form-item-text"/>
      </div>

      <div class="form-item">
        <label>性别</label>

        <label for="male"></label>
        <input id="male" type="radio" name="gender" value="1" v-model="domain.gender" class="form-item-radio"/>
        <label for="female"></label>
        <input id="female" type="radio" name="gender" value="2" v-model="domain.gender" class="king-input-radio"/>
      </div>

      <div class="form-item">
        <label>性格标签</label>

        <label for="game">游戏</label>
        <input id="game" type="checkbox" name="tags" value="游戏" v-model="domain.tags" class="king-input-radio"/>
        <label for="sport">运动</label>
        <input id="sport" type="checkbox" name="tags" value="运动" v-model="domain.tags" class="king-input-radio"/>
        <label for="read">读书</label>
        <input id="read" type="checkbox" name="tags" value="读书" v-model="domain.tags" class="king-input-radio"/>
      </div>

      <div class="form-item">
        <label>学校经历</label>
        <label for="MIT">MIT</label>
        <input id="MIT" type="checkbox" name="school" value="MIT" v-model="domain.other.school"
               class="king-input-radio"/>

        <label for="TSU">TSU</label>
        <input id="TSU" type="checkbox" name="school" value="TSU" v-model="domain.other.school"
               class="king-input-radio"/>
      </div>

      <div class="form-item">
        <label>工作经历1</label>
        <input id="exp1" type="text" name="exp1" v-model="domain.other.work.exp1"
               class="king-input-text"/>
      </div>

      <div class="form-item">
        <label>工作经历2</label>
        <input id="exp2" type="text" name="exp2" v-model="domain.other.work.exp2"
               class="king-input-text"/>
      </div>

      <button @click="onClick">提交</button>
    </form>
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# 业务组件(父组件) Test

<script setup>
import {ref} from "vue";
import TestComponent from "@/views/TestComponent.vue";

const profileDomain = ref({
  username: '阿迪王',
  gender: 1,
  tags: ['体育', '游戏'],
  other: {
    school: ['MIT'],
    work: {
      exp1: '销售',
      exp2: '技术',
    }
  },
})
const processSubmit = (domain) => {
  console.log("提交结果:", domain)
}

const processChange = (domain) => {
  profileDomain.value = domain
}
</script>

<template>
  <div class="test">
    <TestComponent @submit="processSubmit" @change="processChange" :domain="profileDomain"/>
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30