美文网首页
vue 组件传多个值 多个事件的简单写法

vue 组件传多个值 多个事件的简单写法

作者: 黎明的叶子 | 来源:发表于2022-08-09 11:40 被阅读0次

1.父页面调用写法:

<searchFormC
        :formOptions="formOptions"
        :btnItems="btnItems" 
      ></searchFormC>

// 引入
import searchFormC from "../common/form/searchForm.vue";

// data里面定义
formOptions: [
        {
          label: "",
          prop: "title",
          element: "el-input",
          placeholder:'请输入关键字进行查询',
          "prefix-icon": "el-icon-search",
          clearable: true,
        },
      ],
// 也可以将其定义为计算属性,加入按钮显示不显示的判断
btnItemsNoLink: [
        {
          id: "search",
          size: "mini",
          type: "primary",
          disabled: false,
          text: "查询",
          events: {
            click: (val, e) => {
              // 本页面方法
              this.onSearch(val);
            },
          },
        },
        {
          id: "batchAdd",
          size: "mini",
          type: "primary",
          disabled: true,
          text: "批量添加",
          events: {
            click: () => {
              this.onBatchAdd();
            },
          },
        },
      ], 

2.搜索栏公共组件

<!--搜索栏公共组件-->
<template>
  <div class="search-form-box">
    <el-form class="form-box" ref="formRef" :model="formData" :inline="true">
      <el-form-item
        v-for="(item, index) in formOptions"
        :key="newKeys[index]"
        :prop="item.prop"
        :label="item.label ? item.label + ': ' : ''"
        :rules="item.rules"
      >
        <formItem v-model="formData[item.prop]" :itemOptions="item"></formItem>
      </el-form-item>
    </el-form>
    <!-- 提交按钮 -->
    <div class="btn-box">
      <template v-for="(item, index) in btnItems">
        <buttonItem :key="index" :itemOptions="item" :formData="formData"></buttonItem>
      </template> 
    </div>
  </div>
</template>

<script>
import formItem from "./formItem";
import buttonItem from "./buttonItem.vue";
import { createUniqueString } from "../../../utils/tools";
export default {
  props: {
    /**
     * 表单配置
     * 示例:
     * [{
     * label: '用户名', // label文字
     * prop: 'username', // 字段名
     * element: 'el-input', // 指定elementui组件
     * initValue: '阿黄', // 字段初始值
     * placeholder: '请输入用户名', // elementui组件属性
     * rules: [{ required: true, message: '必填项', trigger: 'blur' }], // elementui组件属性
     * events: { // elementui组件方法
     *  input (val) {
     *  console.log(val)
     *  },
     *  ...... // 可添加任意elementui组件支持的方法
     * }
     * ...... // 可添加任意elementui组件支持的属性
     * }]
     */
    formOptions: {
      type: Array,
      required: true,
      default() {
        return [];
      },
    }, 
    /**
     * 提交按钮项,按钮配置
     * 示例:
     * [
        {
          size:"mini",
          type:"primary",
          disabled:false,
          text:"查询",
          events:{
            click(val,e){
              console.log(val,e) 
            }
            ...... // 可添加任意elementui组件支持的方法
          }
        }
         ...... // 可添加任意elementui组件支持的属性
      ] 
     */
    btnItems: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      formData: {},
    };
  },
  components: { formItem ,buttonItem},
  computed: {
    newKeys() { 
      return this.formOptions.map((v) => {
        return createUniqueString();
      });
    },
  },
  created() {
    this.addInitValue(); 
  },
  mounted() {},
  methods: {
    // 校验
    onValidate(callback) {
      this.$refs.formRef.validate((valid) => {
        if (valid) {
          // console.log("提交成功");
          // console.log(this.formData);
          callback();
        }
      });
    },
   
    // 添加初始值
    addInitValue() {
      const obj = {};
      this.formOptions.forEach((v) => {
        if (v.initValue !== undefined) {
          obj[v.prop] = v.initValue;
        }
      });
      this.formData = obj;
    },
  },
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>
.search-form-box {
  margin-top: 5px;
  display: flex;
}

.form-box {
  margin-left: 5px;
}

.btn-box {
  padding-top: 5px;
  display: flex;
}

button {
  height: 28px;
}

.el-form-item {
  margin-bottom: 5px;
}
</style>

3.按钮组件写法
使用v-on完成多个事件的绑定,解决回调传参问题。参考bindBtnEvents方法

<template>
  <div class="btn-item">
    <el-button plain v-bind="bindBtnProps" v-on="bindBtnEvents">
      {{ itemOptions.text }}</el-button
    >
  </div>
</template>

<script>
export default {
  inheritAttrs: false,
  props: {
    itemOptions: {
      type: Object,
      default() {
        return {};
      },
    },
    formData: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {};
  },
  components: {},
  computed: {
    bindBtnProps() {
      let obj = { ...this.itemOptions };
      // 移除冗余属性
      delete obj.text;
      delete obj.events;
      return obj;
    },
    // 绑定方法
    bindBtnEvents() {
      let events = this.itemOptions.events;
      if (!events) {
        return {};
      }   
      let result = Object.keys(events).reduce((cur,next)=>{
        cur[next] = events[next].bind(this,this.formData)
        return cur
      },{})  
      return result;
    },
  },
  mounted() {},
  methods: {},
};
</script> 
<style lang="stylus" rel="stylesheet/stylus" scoped>
 .btn-item{
  margin-left: 5px;
 }
</style>

4.formItem 组件写法

<template>
  <div class="form-item">
    <el-input
      v-if="isInput"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      size="mini" 
    ></el-input> 
    
    <el-input-number
      v-if="isInputNumber"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      :controls-position="itemOptions['controls-position'] || 'right'"
      size="mini"
    ></el-input-number>

    <el-select
      v-if="isSelect"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      size="mini"
      clearable
    >
      <el-option
        v-for="item in itemOptions.options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      ></el-option>
    </el-select>

    <!-- datetimerange/daterange -->
    <el-date-picker
      v-if="isDatePickerDateRange"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      :type="itemOptions.type || 'datetimerange'"
      size="mini"
      clearable
      :picker-options="pickerOptionsRange"
      start-placeholder="开始日期"
      range-separator="至"
      end-placeholder="结束日期"
      :default-time="['00:00:00', '23:59:59']"
      value-format="yyyy-MM-dd HH:mm:ss"
    ></el-date-picker>

    <!-- monthrange -->
    <el-date-picker
      v-if="isDatePickerMonthRange"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      type="monthrange"
      size="mini"
      clearable
      :picker-options="pickerOptionsRangeMonth"
      start-placeholder="开始日期"
      range-separator="至"
      end-placeholder="结束日期"
      value-format="yyyy-MM"
    ></el-date-picker>

    <!-- others -->
    <el-date-picker
      v-if="isDatePickerOthers"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      :type="itemOptions.type"
      size="mini"
      clearable
      placeholder="请选择日期"
    ></el-date-picker>

    <el-cascader
      v-if="isCascader"
      v-model="currentVal"
      v-bind="bindProps"
      v-on="bindEvents"
      size="mini"
      clearable
    ></el-cascader>
  </div>
</template>

<script>
import {pickerOptionsRange,pickerOptionsRangeMonth} from "@/utils/tools";
export default {
  inheritAttrs: false,
  props: {
    value: {},
    itemOptions: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      pickerOptionsRange: pickerOptionsRange,
      pickerOptionsRangeMonth: pickerOptionsRangeMonth,
    };
  },
  components: {},
  computed: {
    currentVal: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit("input", val);
      },
    },
    bindProps() {
      let obj = { ...this.itemOptions };
      // 移除冗余属性
      delete obj.label;
      delete obj.prop;
      delete obj.element;
      delete obj.initValue;
      delete obj.rules;
      delete obj.events;
      if (obj.element === "el-select") {
        delete obj.options;
      }
      return obj;
    },
    // 绑定方法
    bindEvents() {
      return this.itemOptions.events || {};
    },
    // el-input
    isInput() {
      return this.itemOptions.element === "el-input";
    },
    // el-input-number
    isInputNumber() {
      return this.itemOptions.element === "el-input-number";
    },
    // el-select
    isSelect() {
      return this.itemOptions.element === "el-select";
    },
    // el-date-picker (type: datetimerange/daterange)
    isDatePickerDateRange() {
      const isDatePicker = this.itemOptions.element === "el-date-picker";
      const isDateRange =
        !this.itemOptions.type ||
        this.itemOptions.type === "datetimerange" ||
        this.itemOptions.type === "daterange";
      return isDatePicker && isDateRange;
    },
    // el-date-picker (type: monthrange)
    isDatePickerMonthRange() {
      const isDatePicker = this.itemOptions.element === "el-date-picker";
      const isMonthRange = this.itemOptions.type === "monthrange";
      return isDatePicker && isMonthRange;
    },
    // el-date-picker (type: other)
    isDatePickerOthers() {
      const isDatePicker = this.itemOptions.element === "el-date-picker";
      return (
        isDatePicker &&
        !this.isDatePickerDateRange &&
        !this.isDatePickerMonthRange
      );
    },
    // el-cascader
    isCascader() {
      return this.itemOptions.element === "el-cascader";
    },
  },
  mounted() {},
  methods: {},
};
</script> 

5.tool.js

/**
 * 创建唯一的字符串
 * @return {string} ojgdvbvaua40
 */
export function createUniqueString() {
    const timestamp = +new Date() + ''
    const randomNum = parseInt((1 + Math.random()) * 65536) + ''
    return (+(randomNum + timestamp)).toString(32)
}

// elementui日期时间范围 快捷选项
export const pickerOptionsRange = {
    shortcuts: [{
        text: '今天',
        onClick(picker) {
            const end = new Date()
            const start = new Date(new Date().toDateString())
            start.setTime(start.getTime())
            picker.$emit('pick', [start, end])
        }
    }, {
        text: '最近一周',
        onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(end.getTime() - 3600 * 1000 * 24 * 7)
            picker.$emit('pick', [start, end])
        }
    }, {
        text: '最近一个月',
        onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
            picker.$emit('pick', [start, end])
        }
    }, {
        text: '最近三个月',
        onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
            picker.$emit('pick', [start, end])
        }
    }]
}

// elementui月份范围 快捷选项
export const pickerOptionsRangeMonth = {
    shortcuts: [{
            text: '今年至今',
            onClick(picker) {
                const end = new Date()
                const start = new Date(new Date().getFullYear(), 0)
                picker.$emit('pick', [start, end])
            }
        },
        {
            text: '最近半年',
            onClick(picker) {
                const end = new Date()
                const start = new Date()
                start.setMonth(start.getMonth() - 6)
                picker.$emit('pick', [start, end])
            }
        },
        {
            text: '最近一年',
            onClick(picker) {
                const end = new Date()
                const start = new Date()
                start.setMonth(start.getMonth() - 12)
                picker.$emit('pick', [start, end])
            }
        }
    ]
}

 

相关文章

  • Day5 拾遗 emit

    vue emit多个参数利用arguments来获取子组件传值或者兄弟组件通过emit传值, 通过argument...

  • vue逆向传值

    vue返回上个页面逆向传值传多个值

  • Vue 笔记

    Vue事件多个参数 如@change事件,需要传多个参数,@change=“changes(index)” 事件...

  • uniApp自定义组件

    自定义组件代码 语法,传参,事件跟VUE一致 ,请参数vue的写法

  • Vue组件间通信

    Vue组件间通信 父子组间通信 通过props向子组件传值,通过事件向父级组件发送消息 通过props向子组件传值...

  • vue使用bus进行兄弟组件传值

    方法一:通过bus中转 如果要传多个值: 如果需要不触发事件,就把值传递给兄弟组件,那么必须通过异步的方法传递,例...

  • VUE03

    Vue组件 组件的创建 组件的指令以及事件绑定 父子组件创建 父子组件通信 兄弟组件的传值 动态组件

  • ionic4-传递参数

    环境 路由传值 方式一(单个值) 路由定义 跳转 或者 接收 方式二(多个值) 跳转 接收 组件间传值 父 -> ...

  • Vue 中的 .sync 修饰符的作用

    是在父组件中对引用的子组件的对子组件传值以及接收子组件回传的值,这些操作所需语法的一个简化写法,是一个Vue提供给...

  • 所有页面头部组件封装:组件传值

    多个父组件向同一个子组件传值子组件: 默认背景色 默认传订单详情 父组件传值title=" " 填写任何内容都可以...

网友评论

      本文标题:vue 组件传多个值 多个事件的简单写法

      本文链接:https://www.haomeiwen.com/subject/kdtawrtx.html