内置组件components使用总结

92 阅读2分钟

配合keep-alive组件使用

<template>
2  <div id="app">
3    <button @click="changeComponent">切换组件</button>
4    <keep-alive>
5      <component :is="currentComponent"></component>
6    </keep-alive>
7  </div>
8</template>
// 这种使用方式虽然隐藏的组件并不会被销毁组件,这在组件切换的时候能做一些事情(缓存数据,提升组件的性能)但是也有相应的弊端,但是也不会被挂载到dom上(即不会被refs访问到)

配合v-for使用即可实现循环遍历组件的作用,在多步骤表单业务(跨页面跨组件表单校验)代码中,用于提升组件的抽离程度

<template>
  <div>
    <div>
      <el-steps
        :active="currentStep"
        finish-status="success"
      >
        <el-step
          finish-status="success"
          :title="item.title"
          v-for="(item, index) in componentsList"
          :key="item.index"
        ></el-step>
      </el-steps>
      <component
        v-for="(item, index) in componentsList"
        :is="item.is"
        :key="index"
        v-show="item.isshow"
        :ref="`stepForm${item.name}`"
      ></component>
      <el-button
        style="margin-top: 12px"
        @click="next"
      >
        下一步
      </el-button>
      <el-button @click="submitForm">提交</el-button>
    </div>
  </div>
</template>

<script>
const obj = {
  1: 'child1',
  2: 'child2'
}
import child1 from './componennts/child1.vue'
import child2 from './componennts/child2.vue'
export default {
  components: {
    child1,
    child2
  },
  data() {
    return {
      is: 'child1',
      componentsList: [
        {
          title: '步骤一',
          name: 1,
          is: 'child1',
          isshow: true
        },
        {
          title: '步骤二',
          name: 2,
          is: 'child2',
          isshow: false
        }
      ],
      currentStep: 1
    }
  },
  watch: {
    currentStep(value) {
      this.componentsList.forEach((element, index) => {
        element.isshow = index + 1 === value
      })
      console.log(this.componentsList, ' this.componentsList')
    }
  },
  methods: {
    handleClick() {},
    next() {
      this.currentStep++
      if (this.currentStep > 2) {
        this.currentStep = 1
      }
      this.is = obj[this.currentStep]
    },
    async submitForm() {
      const formDataArray = []
      let isValid = true
      // 假设 currentStep 是当前步骤,stepForms 是所有步骤组件的引用数组
      for (let step of this.componentsList) {
        const stepRefName = `stepForm${step.name}`
        const componentInstance = this.$refs[stepRefName]
        console.log(componentInstance, 'componentInstance')
        if (componentInstance && componentInstance[0].validate) {
          const validateResult = await componentInstance[0].validate()
          if (!validateResult) {
            isValid = false
            break // 任何一个步骤验证失败即跳出循环
          }
        } else {
          console.warn(`Component ${stepRefName} validation method not found.`)
        }
      }
      // console.log(formDataArray, 'formDataArray')

      // 合并所有表单数据,这里简单合并为一个数组,实际可能需要更复杂的逻辑来组合数据
      const allFormData = formDataArray.reduce(
        (acc, curr) => ({ ...acc, ...curr }),
        {}
      )
      // isValid 最终为true 才发送请求
      // 发送请求
      // this.sendRequest(allFormData)
    }
  }
}
</script>
// 子组件
<template>
  <div>
    <h1>子组件一</h1>
    <el-form
      :model="ruleForm"
      :rules="rules"
      ref="ruleForm1"
      label-width="100px"
      class="demo-ruleForm"
    >
      <el-form-item
        label="活动名称"
        prop="name"
      >
        <el-input v-model="ruleForm.name"></el-input>
      </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>
export default {
  data() {
    return {
      ruleForm: {
        name: '',
        region: '',
        date1: '',
        date2: '',
        delivery: false,
        type: [],
        resource: '',
        desc: ''
      },
      rules: {
        name: [
          { required: true, message: '请输入活动名称', trigger: 'blur' },
          { min: 3, max: 5, 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: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          alert('submit!')
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    submit() {},
    validate() {
      // 这里应该调用el-form的validate方法并返回Promise
      return this.$refs['ruleForm1'].validate((valid) => {
        return valid
      })
    }
    //      getFormData() {
    // 7      return this.ruleForm;
    // 8    }
  }
}
</script>

在封装表单组件的时候,通过components可以传递组件的位置给表单组件,表单组件通过import动态引入,通过default属性的值,通过is属性进行展示(这里以vue2为例)