实现一个vue2嵌套组件demo

24 阅读1分钟

写一个基本的嵌套组件demo,仿照ELement的form组件

做了以下小功能点:

  1. 包裹组件向被包裹组件传递参数formrules
  2. 被包裹组件反向传递校验函数,包裹组件的getCheck获取被包裹组件的check
  3. 外部使用validate方法,进行两层组件的值校验
  • 引用
<template>
  <yys-father ref="Father" :form="form" :rules="rules">
    <yys-children prop="name">
      <input v-model="form.name" type="text" />
    </yys-children>
    <br />
    <yys-children prop="sex">
      <input v-model="form.sex" type="text" />
    </yys-children>
    <br />
    <button @click="submit()">测试</button>
  </yys-father>
</template>

<script>
import yysFather from '../components/yys-father.vue'
import yysChildren from '../components/yys-children.vue'

export default {
  name: 'Home',
  components: {
    yysFather,
    yysChildren
  },
  data() {
    return {
      form: {
        name: '张三',
        sex: '男'
      },
      rules: {
        name: {
          notNull: true
        },
        sex: {
          notNull: false
        }
      }
    }
  },
  methods: {
    submit() {
      this.$refs.Father.validate().then(res => {
        console.log(200, res)
      })
    }
  }
}
</script>
  • 包裹组件
<template>
  <div>
    <h1>测试input</h1>
    <slot />
  </div>
</template>

<script>
export default {
  props: {
    form: {
      type: Object,
      default: () => {}
    },
    rules: {
      type: Object,
      default: () => {}
    }
  },
  provide() {
    return {
      formData: this.form,
      rulesData: this.rules,
      getCheck: cb => {
        this.checkList.push(cb)
      }
    }
  },
  data: () => {
    return {
      // 校验列表
      checkList: []
    }
  },
  methods: {
    validate() {
      return new Promise((resolve, reject) => {
        try {
          let boo = true
          this.checkList.forEach(e => {
            const _b = e()
            if (_b) boo = false
          })
          if (boo) {
            alert('有必填项未填')
          } else {
            alert('可以提交')
          }
          resolve(boo)
        } catch (err) {
          reject(err)
        }
      })
    }
  }
}
</script>
  • 被包裹组件
<template>
  <div>
    <span style="color:red">{{ '*' }}</span>
    <slot />
    <span>{{ showText ? text : null }}</span>
  </div>
</template>

<script>
export default {
  inject: ['formData', 'rulesData', 'getCheck'],
  props: {
    prop: {
      type: String,
      default: ''
    },
    text: {
      type: String,
      default: '请填写'
    }
  },
  data: () => {
    return {
      showText: false
    }
  },
  created() {
    if (this.rulesData[this.prop]) {
      if (this.rulesData[this.prop].notNull) {
        // 将当前行校验上报
        this.getCheck(() => this.check())
      }
    }
  },
  methods: {
    check() {
      if (!this.formData[this.prop]) {
        this.showText = true
        return false
      }
      this.showText = false
      return true
    }
  }
}
</script>