基于elementui封装的treeSelect 树形选择组件,以及自定义组件在form表单的校验问题

基于elementui封装的treeSelect 树形选择组件,以及自定义组件在form表单的校验问题

treeSelect组件

<template>
  <div ref="container">
    <el-popover
      :width="this.width || this.containerWidth"
      placement="bottom-start"
      title=""
      trigger="click"
    >
      <el-input
        :readonly="true"
        placeholder="请输入内容"
        slot="reference"
        suffix-icon="el-icon-arrow-down"
        v-model="value"
      >
      </el-input>
      <el-tree
        :data="data"
        :props="defaultProps"
        @node-click="handleNodeClick"
      ></el-tree>
    </el-popover>
  </div>
</template>
<script>
export default {
  name: "treeSelect",
  data () {
    return {
      value: "",

      valueArr: [],
      containerWidth: 400
    }
  },
  mounted () {
    console.log(this.$refs.container.offsetWidth)
    this.containerWidth = this.$refs.container.offsetWidth
  },
  model: {
    prop: "defaultValue",
    event: 'change'
  },
  props: {
    // defaultProps: {
    //   children: 'children1',
    //   label: 'label1'
    // },
    defaultProps: {
      type: Object,
      required: true
    },
    width: {
      type: Number
    },
    // data: [{
    //   label1: '一级 1',
    //   children1: [{
    //     label1: '二级 1-1',
    //     children1: [{
    //       label1: '三级 1-1-1'
    //     }]
    //   }]
    // }],
    // tree 选项
    data: {
      type: Array,
      required: true
    },
    defaultValue: {
      type: String
    },
    // 是否显示所有层级
    showAllLevels: {
      type: Boolean,
      default: true
    },
    // 分隔符
    separator: {
      type: String,
      default: "/"
    }
  },
  watch: {
    defaultValue: {
      immediate: true,
      handler (val) {
        this.value = val
      }
    }
  },
  methods: {
    // 清空form表单校验(自定义组件)
    // this.$refs['formItem'].$emit('el.form.blur', v)
    handleNodeClick (data, node) {
      console.log(data, node)
      this.valueArr = []
      this.handleGetNodeName(node)
      this.valueArr.push(data[this.defaultProps.label])
      if (this.showAllLevels) {
        this.value = this.valueArr.join(this.separator)
      } else {
        this.value = this.valueArr[this.valueArr.length - 1]
      }
      this.$emit('change', this.value)
      this.$emit('handleGetValue', {
        data, node
      })
    },
    // 获取节点名称递归
    handleGetNodeName (node) {
      if (node.parent.label) {
        this.valueArr.unshift(node.parent.label)
        this.handleGetNodeName(node.parent)
      }
    }
  },
  computed: {

  }
}
</script>

子组件在form表单的使用

<template>
  <div style="background: #fff">
    <el-form
      :model="ruleForm"
      :rules="rules"
      ref="ruleForm"
      label-width="100px"
      class="demo-ruleForm"
    >
      <el-form-item ref="formItem" label="活动名称" prop="name">
        <!-- <el-input v-model="ruleForm.name"></el-input> -->
        <tree-select
          @handleGetValue="handleGetValue"
          :data="data"
          :defaultProps="defaultProps"
          v-model="ruleForm.name"
        />
      </el-form-item>
      <el-form-item label="活动区域" prop="region">
        <el-select v-model="ruleForm.region" placeholder="请选择活动区域">
          <el-option label="区域一" value="shanghai"></el-option>
          <el-option label="区域二" value="beijing"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="活动时间" required>
        <el-col :span="11">
          <el-form-item prop="date1">
            <el-date-picker
              type="date"
              placeholder="选择日期"
              v-model="ruleForm.date1"
              style="width: 100%"
            ></el-date-picker>
          </el-form-item>
        </el-col>
        <el-col class="line" :span="2">-</el-col>
        <el-col :span="11">
          <el-form-item prop="date2">
            <el-time-picker
              placeholder="选择时间"
              v-model="ruleForm.date2"
              style="width: 100%"
            ></el-time-picker>
          </el-form-item>
        </el-col>
      </el-form-item>
      <el-form-item label="即时配送" prop="delivery">
        <el-switch v-model="ruleForm.delivery"></el-switch>
      </el-form-item>
      <el-form-item label="活动性质" prop="type">
        <el-checkbox-group v-model="ruleForm.type">
          <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
          <el-checkbox label="地推活动" name="type"></el-checkbox>
          <el-checkbox label="线下主题活动" name="type"></el-checkbox>
          <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
        </el-checkbox-group>
      </el-form-item>
      <el-form-item label="特殊资源" prop="resource">
        <el-radio-group v-model="ruleForm.resource">
          <el-radio label="线上品牌商赞助"></el-radio>
          <el-radio label="线下场地免费"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="活动形式" prop="desc">
        <el-input type="textarea" v-model="ruleForm.desc"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('ruleForm')"
          >立即创建</el-button
        >
        <el-button @click="resetForm('ruleForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import treeSelect from "./treeSelect.vue"
export default {
  name: "Test",
  components: {
    treeSelect
  },
  data () {
    return {
      defaultProps: {
        children: 'children1',
        label: 'label1'
      },
      data: [{
        label1: '一级 1',
        children1: [{
          label1: '二级 1-1',
          children1: [{
            label1: '三级 1-1-1'
          }]
        }]
      }],
      ruleForm: {
        name: '',
        region: '',
        date1: '',
        date2: '',
        delivery: false,
        type: [],
        resource: '',
        desc: ''
      },
      rules: {
        name: [
          { required: true, message: '请输入活动名称', trigger: 'blur' },
          { min: 1, max: 50, message: '长度在 3 到 5 个字符', trigger: 'blur' }
        ],
        region: [
          { required: true, message: '请选择活动区域', trigger: 'change' }
        ],
        date1: [
          { type: 'date', required: true, message: '请选择日期', trigger: 'change' }
        ],
        date2: [
          { type: 'date', required: true, message: '请选择时间', trigger: 'change' }
        ],
        type: [
          { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
        ],
        resource: [
          { required: true, message: '请选择活动资源', trigger: 'change' }
        ],
        desc: [
          { required: true, message: '请填写活动形式', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // 选中值以及详细节点的回调
    handleGetValue (v) {
      console.log(v)
      // 用于清除form校验
      this.$refs['formItem'].$emit('el.form.blur', v)
    },
    submitForm (formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          alert('submit!')
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetForm (formName) {
      this.$refs[formName].resetFields()
    }
  }
}
</script>

<style scoped>
</style>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
封装一个树形选择组件可以分为以下几个步骤: 1. 定义组件的 props:需要传入一个树形结构的数据,以及选中的节点的值。 ``` props: { treeData: { type: Array, required: true }, selectedValue: { type: String, default: '' } } ``` 2. 在组件中渲染树形结构:可以使用递归组件来渲染,每个节点使用一个复选框来表示是否选中,以及一个展开/收起按钮来展示子节点。 ``` <template> <div> <ul> <li v-for="node in treeData" :key="node.id"> <label> <input type="checkbox" :value="node.value" :checked="isSelected(node)"> {{node.label}} </label> <button v-if="node.children" @click="toggle(node)"> {{node.expanded ? '-' : '+'}} </button> <tree-select v-if="node.children && node.expanded" :treeData="node.children" :selectedValue="selectedValue" @input="onInput"></tree-select> </li> </ul> </div> </template> ``` 3. 实现选中节点的处理:当选中一个节点时,需要将它的值加入到选中节点的列表中;取消选中时,需要将它从选中节点的列表中删除。 ``` methods: { isSelected(node) { return this.selectedValue.includes(node.value) }, onInput(value) { this.$emit('input', value) } } ``` 4. 实现展开/收起节点的处理:当展开/收起一个节点时,需要将它的子节点渲染或移除。 ``` methods: { toggle(node) { node.expanded = !node.expanded } } ``` 最终的代码可以参考下面的例子: ``` <template> <div> <ul> <li v-for="node in treeData" :key="node.id"> <label> <input type="checkbox" :value="node.value" :checked="isSelected(node)"> {{node.label}} </label> <button v-if="node.children" @click="toggle(node)"> {{node.expanded ? '-' : '+'}} </button> <tree-select v-if="node.children && node.expanded" :treeData="node.children" :selectedValue="selectedValue" @input="onInput"></tree-select> </li> </ul> </div> </template> <script> export default { name: 'TreeSelect', props: { treeData: { type: Array, required: true }, selectedValue: { type: String, default: '' } }, methods: { isSelected(node) { return this.selectedValue.includes(node.value) }, onInput(value) { this.$emit('input', value) }, toggle(node) { node.expanded = !node.expanded } } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值