Vue组件开发:和组件之间交互数据 v-model的实现

By | 2018年12月11日

1、需求

后台开发时,用户搜索功能经常用到。每次都写一遍用户搜索的代码,导致代码有很多冗余,而且修改起来要修改多处。所以需要自定义一个组件,来实现用户搜索功能。

一般vue和组件的交互有两种,一是通过事件,像父组件传递数据;另一种就是使用v-model。这里使用v-model即可。

我希望的调用方式比较简单,代码如下:

<user-search v-model="transferForm.userId"></user-search>

2、组件的代码编写

2.1、视图代码的编写

我的代码是基于element-ui的:

<template>
    <div>
        <el-form-item label="查找用户">
            <el-col :span="18">
                <el-input v-model="search" placeholder="编号、用户名、手机号码、邮箱、备注等字段"></el-input>
            </el-col>
            <el-col :span="4">
                <el-button @click.prevent="searchUser">查找</el-button>
            </el-col>
        </el-form-item>
        <el-form-item label="导入至用户">
                <el-select
                v-model="userId"
                allow-create
                default-first-option
                placeholder="请选择或者输入需要导入的用户编号">
                <el-option
                v-for="item in searchResult"
                :key="item.id"
                :label="'编号:'+item.id+',用户名:'+item.username+',邮箱:'+item.email+',手机号:'+item.mobile+'备注:'+item.comment"
                :value="item.id">
                </el-option>
            </el-select>
        </el-form-item>
    </div>
</template>

2.2、接收父组件v-model的数据:

data() {
  return {
    search: "",
    searchResult: [],
    userId: undefined //组件内的userId变量
  };
},
model: {
  prop: "modelValue" //这个定义props中那个值是v-model;字段名是随便定义的,不一定要modelValue
},
props:{
    modelValue:Number 
},
created(){
    this.userId = this.modelValue  //把v-model的值传给自身的userId
},

 

2.3、当输入框变化的时候,执行查询操作

这个比较简单,直接在button上绑定事件即可

视图代码:

<el-button @click.prevent="searchUser">查找</el-button>

js代码:

methods: {
    searchUser() {
      if (this.search) {
        axios
          .get("/admin/user/importSearch.json", {
            params: { search: this.search }
          })
          .then(response => {
            const data = response.data;
            if (data.result == "success") {
              this.searchResult = data.list;
            } else {
              this.$message.error(data.message);
            }
          })
          .catch(err => {
            let msg = err.errmsg ? err.errmsg : err.message;
            this.$message.error(msg);
          });
      }
    }

2.4、监听userId的变化,并发送给父组件

watch:{
      userId(val){
          this.$emit('input', val); //这里最重要,是触发父组件的input事件实现的。input是个特定的事件
      }
  },

3、在组件里面调用该组件

3.1、引入该组件

import UserSearch from '../common/user-search.vue';
export default {
  components: {
    UserSearch
  },
  //其他代码省略咯
}

3.2、调用组件

组件调用:

<user-search v-model="transferForm.userId"></user-search>

绑定数据:

export default{
    data() {
        return {
            transferForm:{}
        }
    },
    //其他代码省略了
}

 

4、组件完整代码:

<template>
    <div>
        <el-form-item label="查找用户">
            <el-col :span="18">
                <el-input v-model="search" placeholder="编号、用户名、手机号码、邮箱、备注等字段"></el-input>
            </el-col>
            <el-col :span="4">
                <el-button @click.prevent="searchUser">查找</el-button>
            </el-col>
        </el-form-item>
        <el-form-item label="导入至用户">
                <el-select
                v-model="userId"
                allow-create
                default-first-option
                placeholder="请选择或者输入需要导入的用户编号">
                <el-option
                v-for="item in searchResult"
                :key="item.id"
                :label="'编号:'+item.id+',用户名:'+item.username+',邮箱:'+item.email+',手机号:'+item.mobile+'备注:'+item.comment"
                :value="item.id">
                </el-option>
            </el-select>
        </el-form-item>
    </div>
</template>
<script>
import { axios } from "init";
export default {
  name: "user-search",
  data() {
    return {
      search: "",
      searchResult: [],
      userId:undefined
    };
  },
  model: {
    prop: "modelValue"
  },
  props:{
      modelValue:Number
  },
  watch: {
    userId(val) {
      this.$emit("input", val);
    }
  },
  created(){
      this.userId = this.modelValue
  },
  methods: {
    searchUser() {
      if (this.search) {
        axios
          .get("/admin/user/importSearch.json", {
            params: { search: this.search }
          })
          .then(response => {
            const data = response.data;
            if (data.result == "success") {
              this.searchResult = data.list;
            } else {
              this.$message.error(data.message);
            }
          })
          .catch(err => {
            let msg = err.errmsg ? err.errmsg : err.message;
            this.$message.error(msg);
          });
      }
    }
  }
};
</script>