Vue表单类组件封装思路

编程 · 2023-12-05 · 214 人浏览

核心步骤

  1. 子组件中:props通过value接收,事件触发input
  2. 父组件中:v-model给组件直接绑数据

src\components\BaseSelect.vue文件:

<template>
  <div>
    <select :value="value" @change="handleChange">
      <option value="101">北京</option>
      <option value="102">上海</option>
      <option value="103">广州</option>
      <option value="104">深圳</option>
    </select>
  </div>
</template>

<script>
export default {
  props: {
    value: String,
  },
  methods: {
    handleChange(e) {
      this.$emit('input', e.target.value)
    },
  },
}
</script>

src\App.vue文件:

<template>
  <div>
    <BaseSelect v-model="selectId"></BaseSelect>
  </div>
</template>

<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
  data() {
    return {
      selectId: '102',
    }
  },
  components: {
    BaseSelect,
  },
}
</script>

.sync修饰符

作用:可以实现子组件与父组件数据的双向绑定,简化代码。

特点:prop属性名可以自定义,非固定为value。

场景:封装弹框类的基础组件,visible属性:true显示、false隐藏。

本质:就是:属性名@update:属性名合写。

src\components\BaseDialog.vue文件:

<template>
  <div v-show="visible" class="base-dialog-mask">
    <div class="base-dialog">
      <div class="title">
        <h3>温馨提示</h3>
        <button class="close" @click="close">x</button>
      </div>

      <div class="content"><p>确认退出本系统么?</p></div>

      <div class="footer">
        <button>确认</button>
        <button>取消</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    visible: Boolean,
  },
  methods: {
    close() {
      this.$emit('update:visible', false)
    },
  },
}
</script>

<style scoped>
.base-dialog-mask {
  position: fixed;
  left: 50%;
  top: 50%;
  width: 300px;
  height: 200px;
  box-shadow: 2px 2px 2px 2px #ccc;
  transform: translate(-50%, -50%);
  padding: 0 10px;
}
.base-dialog .title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 2px solid #000;
}
.base-dialog .content {
  margin-top: 38px;
}
.base-dialog .title .close {
  width: 20px;
  height: 20px;
  cursor: pointer;
  line-height: 10px;
}
.footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 26px;
}
.footer button {
  width: 80px;
  height: 40px;
}
.footer button:nth-child(1) {
  margin-right: 10px;
  cursor: pointer;
}
</style>

src\App.vue文件:

<template>
  <div class="app">
    <button @click="openDialog">退出按钮</button>
    <BaseDialog :visible.sync="isShow"></BaseDialog>
  </div>
</template>

<script>
import BaseDialog from './components/BaseDialog.vue'
export default {
  data() {
    return {
      isShow: false,
    }
  },
  methods: {
    openDialog() {
      this.isShow = true
    },
  },
  components: {
    BaseDialog,
  },
}
</script>
Vue
Theme Jasmine by Kent Liao