自定义组件使用v-model,太好用了

程序员他爱做梦 2024-02-22 12:25:49
场景描述我们在一个系统中,会出现这样的情况,有一个联系人的下拉框,这个下拉框中的数据是从服务端获取的。在很多页面都需要使用这个联系人(下拉框)。我们通常是这样做的:写一个下拉框组件然后调用接口。这样不仅会造成代码冗余,而且不利于后期的维护。比如说:如果有一天这个要发生变化,如果整个系统中有几十处。难道我们要更改几十处?不会吧。这样好难受呀。有的小伙伴说:这个还不简单:封装成为一个组件呀。

封装成为组件concatPersonSelect.vue<template> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="联系人"> <el-select v-model="form.person" placeholder="请选择活动区域"> <el-option v-for="(item,index) in listAtt" :key="index" :label="item.name" :value="item.id"></el-option> </el-select> </el-form-item></el-form></template><script> export default { data() { return { listAtt:[], form: { person: '', } } }, created() { this.getUserList() }, methods: { // 模拟接口 getUserList(){ setTimeout(()=>{ this.listAtt = [{ name:'张三1',id:1 },{ name:'张三2',id:2 },{ name:'张三3',id:3 },{ name:'张三4',id:4 }] },1600) } }, }</script>

页面使用<template> <div> <h2>自定义组件也可以使用v-model</h2> <concatPersonSelect></concatPersonSelect> </div></template><script>export default { components:{ concatPersonSelect }, data(){ return{ } }}</script>

现在遇见的问题csharp是的,现在我们是把它封装成为了一个组件。但是如果获取组件中的值呢?这........,思考一会。机智的小伙伴说:子组件提供一个方法,父组件通过ref的方式去调用。那如果要赋值呢?子组件也提供一个方法,父组件去使用。这样就可以获取值,赋值了。(耶,简直是一个天才)这样虽然可以,但是真的优点繁琐,还有其他好的方法吗?我们可以使用v-model,是的,我们给自己封装的组件使用v-model

组件中使用v-model的想法我们给下拉框绑定一个 change 事件,这样值发生变化后。通过 this.$emit 去更新。与此同时,v-model中的值是 data中的 userValue 值。userValue 中的值是从props中来的。然后使用 model 中的 event 属性与 emit 事件保持一致

改造组件,组件可以使用 v-model<template> <el-form ref="form" label-width="80px"> <el-form-item label="联系人"> <el-select @change="changeGetValue" v-model="userValue" placeholder="请选择活动区域"> <el-option v-for="(item,index) in listAtt" :key="index" :label="item.name" :value="item.id"></el-option> </el-select> </el-form-item></el-form></template><script> export default { model: { event: 'input-change', // 这个事件与下面的emit事件与之对应 prop: 'propsInfoValue' // }, props:{ // 父组件传递的值,用于数据回填 propsInfoValue:{ type:String, default:()=>{ return '' } } }, data() { return { listAtt:[], userValue: this.propsInfoValue } }, created() { this.getUserList() }, methods: { // 模拟接口 getUserList(){ setTimeout(()=>{ this.listAtt = [{ name:'张三1',id:'1' },{ name:'张三2',id:'2' },{ name:'张三3',id:'3' },{ name:'张三4',id:'4' }] },1600) }, // 值发生变化会被触发,就去更新 changeGetValue(){ this.$emit('input-change', this.userValue) } } }</script>

页面就可以使用 v-model 了<template> <div> <h2>自定义组件也可以使用v-model</h2> <concatPersonSelect v-model="obj.name" ></concatPersonSelect> <el-button @click="getHandler"> 获取值 </el-button> </div></template>import concatPersonSelect from '../components/concatPersonSelect/concatPersonSelect.vue'export default { components:{ concatPersonSelect }, data(){ return{ obj:{ name:'' } } }, methods: { getHandler(){ console.log('获取的值', this.obj) } }}

现在我们可以获取组件中的值了。并且不需要通过ref这样的方式来获取。这样一来,更加的方便了。

如果有必填参数怎么搞?我们都知道,如果某一个参数是必填的话。在elementui中的form表单中。需要同时满足两个条件,那就是:rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。因此,子组件中的 el-form-item中应该有一个 prop属性,并且这个属性的值与 rules属性中的规则字段相同就行。我们打算在子组件中使用 v-bind="$attrs" 和 inheritAttrs: false,这样页面中的参数可以直接进行传递

更新优化子组件<template> <div> <el-form-item label="联系人" v-bind="$attrs"> <el-select @change="changeGetValue" v-model="userValue" placeholder="请选择联系人"> <el-option v-for="(item,index) in listAtt" :key="index" :label="item.name" :value="item.id"></el-option> </el-select> </el-form-item> </div></template><script> export default { model: { event: 'input-change', // 这个事件与下面的emit事件与之对应 prop: 'propsInfoValue' // }, props:{ // 父组件传递的值,用于数据回填 propsInfoValue:{ type:String, default:()=>{ return '' } } }, inheritAttrs: false, //不让属性直接渲染在根节点上 data() { return { listAtt:[], userValue: this.propsInfoValue } }, created() { this.getUserList() }, methods: { // 模拟接口 getUserList(){ setTimeout(()=>{ this.listAtt = [{ name:'张三1',id:'1' },{ name:'张三2',id:'2' },{ name:'张三3',id:'3' },{ name:'张三4',id:'4' }] },1600) }, // 值发生变化会被触发,就去更新 changeGetValue(){ this.$emit('input-change', this.userValue) } }, }</script>

页面使用<template> <div> <h2>自定义组件也可以使用v-model</h2> <el-form :rules="rules" :model="ruleForm" ref="form" label-width="80px"> <el-form-item label="活动名称" prop="activeName"> <el-input v-model="ruleForm.activeName"></el-input> </el-form-item> <!-- prop中的值必须与验证规则中的字段保持一致,否者无法验证 --> <concatPersonSelect prop="personName" v-model="ruleForm.personName" > </concatPersonSelect> <el-button @click="getHandler"> 获取值 </el-button> </el-form> </div></template><script>export default { components:{ concatPersonSelect }, data(){ return{ // 表单中的字段 ruleForm:{ activeName:'', personName:'' }, // 验证规则以及提示语 rules: { activeName: [ { required: true, message: '请输入活动名称', trigger: 'blur' }, ], personName: [ { required: true, message: '请选联系人', trigger: 'change' } ] } } }, methods: { getHandler(){ console.log('获取的值', this.ruleForm) this.$refs['form'].validate((valid) => { // 验证规则成功 console.log(1,valid) }) } }}</script>

作者:我的div丢了肿么办链接:https://juejin.cn/post/7264600679573733388

0 阅读:0

程序员他爱做梦

简介:感谢大家的关注