Vue 如何使用props、emit实现自定义双向绑定的实现


Posted in Javascript onJune 05, 2020

下面我将使用Vue自带的属性实现简单的双向绑定。

下面的例子就是利用了父组件传给子组件(在子组件定义props属性,在父组件的子组件上绑定属性),子组件传给父组件(在子组件使用$emit()属性定义一个触发方法,在父组件上的子组件监听这个事件)。

import Vue from 'vueEsm' 

var Com = {
  name:'Com',
  props:['val'],
  template:`<input type='text' @input='handleInput'/>`,
  methods: {
    handleInput(e){
      this.$emit("input",e.target.value);
    }
  },
}

new Vue({
   el:'#app',
   data() {
     return {
       value:''
     }
   },
   components:{
    Com
   },
   template:`
   <div>
   <Com @input='post' :val='value'></Com>
   </div>
   `,
   methods:{
    post(data){
      this.value=data;
    }
   }
 })

上面这个例子,在input标签上每次输入时触发原生事件input,在这个事件上绑定了一个handleInput方法,事件每次触发都会执行方法里的$emit属性。该属性里面第一个参数可以定义一个事件名,第二个参数可以传一个参数。这里我们把每次输入的值e.target.value传进去。在父组件的子组件上监听这个事件,定义一个post方法,方法的参数就是传入的数据。然后我们在父组件的data属性里定义一个存储值的变量value。将刚才传入的参数赋给这个变量value。最后在父组件的子组件上绑定一个自定义属性,比如val。将value传给val。在子组件定义一个props属性接受这个val。

这个例子对于理解父组件与子组件传值特别重要。

下方举例说明了我的一个自定义mySelect的实现过程:

<template>
 <div class="select">
  <div class="input" @click="collapse=!collapse">
   <span v-if="currentValue">{{currentLabel||currentValue}}</span>
   <span v-else class="placeholder">{{placeholder}}</span>

   <span :class="collapse?'arrow-down':'arrow-up'"></span>
  </div>

  <div class="option-list" v-show="!collapse">
   <div class="option-item" v-for="item in data" :key="item.id" @click="chooseItem(item)">{{item[itemLabel?itemLabel:'name']}}</div>
  </div>
 </div>
</template>

<script>
 export default {
  name: "mySelect",
  props: [
   'value',
   'placeholder',
   'data',
   'itemLabel',
   'itemValue'
  ],
  data() {
   return {
    collapse: true,
    currentValue: '',
    currentLabel: '',
   }
  },
  watch: {
   value: {
    immediate: true,
    handler(value) {
     this.currentValue = value;
     this.$emit('input', value);
     this.data.forEach(item => {
      if (item[this.itemValue ? this.itemValue : 'id'] == value) {
       return this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
      }
     });
    }
   },
   data:{
    immediate: true,
    handler(arr) {
     if(this.value||!this.currentLabel){
      arr.forEach(item=>{
       if(item[this.itemValue ? this.itemValue : 'id'] == this.value){
        this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
        return;
       }
      })
     }
    }
   }
  },
  methods: {
   chooseItem(item) {
    if (this.currentValue !== item[this.itemValue ? this.itemValue : 'id']) {
     this.$emit('change',item[this.itemValue ? this.itemValue : 'id']);
    }
    this.currentValue = item[this.itemValue ? this.itemValue : 'id'];
    this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
    this.$emit('input', this.currentValue);
    this.collapse = true;
   }
  }
 }
</script>

<style lang="scss" scoped>
 .select {
  position: relative;

  .input {
   width: 100%;
   height: 30px;
   line-height: 30px;
   background-color: #fff;
   border: 1px solid #02b4fe;
   border-radius: 0 3px 3px 0;
   padding-left: 10px;
   color: #666;
   position: relative;
   .placeholder {
    color: #aaa;
   }
  }

  .arrow-down {
   width: 0;
   height: 0;
   border-left: 5px solid transparent;
   border-right: 5px solid transparent;
   border-top: 8px solid #02b4fe;
   position: absolute;
   right: 5px;
   top: 10px;
  }

  .arrow-up {
   width: 0;
   height: 0;
   border-left: 5px solid transparent;
   border-right: 5px solid transparent;
   border-bottom: 8px solid #02b4fe;
   position: absolute;
   right: 5px;
   top: 10px;
  }

  .option-list {
   max-height: 200px;
   overflow-y: scroll;
   position: absolute;
   top: 2rem;
   left: 0;
   z-index: 5;
   width: 100%;
   padding: 0 5px;
   font-size: 10px;
   color: #aaa;
   background-color: #fff;
   text-align: left;
   box-shadow: 0 0 5px rgba(0, 0, 0, .1);
   border: 1px solid rgb(79, 192, 232);

   .option-item {
    text-align: center;
    line-height: 1.5rem;
   }
  }
 }
</style>

如上所示,当声明了mySelect组件之后,在项目中实际使用时,就可以如下所示直接使用:

<template>
 <mySelect v-model="testValue" placeholder="请选择" :data="testArr" item-label="id"
           item-value="name"></mySelect>
</template>
<script>
  import mySelect from './mySelect'
  
  export default{
    components:{
     mySelect
    },
     data(){
      return {
         testValue:'',
         testArr:[]
       }
     },
     mounted(){
      //预置select的下拉选择基础数据,数据为对象数组,包含id和name属性
     }
}
</script>

以上就是一个简单的自定义双向绑定组件的实现,包括简单的使用过程。在vue中的自定义组件,关于props的声明时,还是尽量使用官方建议的对象方式,可以声明属性的默认值和数据类型。我这边偷懒了用的是props的字符串数组简写方式,但是这样的话对使用组件时的错误调试不利。所以,尽量不要学我偷懒噢,亲~~~

到此这篇关于Vue 如何使用props、emit实现自定义双向绑定的实现的文章就介绍到这了,更多相关Vue props、emit实现自定义双向绑定内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jQuery的仿flash的广告轮播
Nov 05 Javascript
Javascript 鼠标移动上去小三角形滑块缓慢跟随效果
Apr 26 Javascript
js获取指定的cookie的具体实现
Feb 20 Javascript
jQuery实现表格颜色交替显示的方法
Mar 09 Javascript
jQuery插件PageSlide实现左右侧栏导航菜单
Apr 12 Javascript
超精准的javascript验证身份证号的具体实现方法
Nov 18 Javascript
JavaScript代码因逗号不规范导致IE不兼容的问题
Feb 25 Javascript
深入理解JavaScript内置函数
Jun 03 Javascript
浅谈express 中间件机制及实现原理
Aug 31 Javascript
浅谈Vue2.0父子组件间事件派发机制
Jan 08 Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
Mar 05 Javascript
vue中关闭eslint的方法分析
Aug 04 Javascript
VueX模块的具体使用(小白教程)
Jun 05 #Javascript
Vuex的热更替如何实现
Jun 05 #Javascript
2分钟实现一个Vue实时直播系统的示例代码
Jun 05 #Javascript
Vue 封装防刷新考试倒计时组件的实现
Jun 05 #Javascript
webpack 如何同时输出压缩和未压缩的文件的实现步骤
Jun 05 #Javascript
vue使用nprogress加载路由进度条的方法
Jun 04 #Javascript
JS+canvas五子棋人机对战实现步骤详解
Jun 04 #Javascript
You might like
PHP面向对象分析设计的经验原则
2008/09/20 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
php流量统计功能的实现代码
2012/09/29 PHP
PHP5常用函数列表(分享)
2013/06/07 PHP
PHP设置进度条的方法
2015/07/08 PHP
Thinkphp5.0框架使用模型Model的获取器、修改器、软删除数据操作示例
2019/10/11 PHP
php与阿里云短信接口接入操作案例分析
2020/05/27 PHP
jquery下checked取值问题的解决方法
2012/08/09 Javascript
jQuery处理json数据返回数组和输出的方法
2015/03/11 Javascript
被遗忘的javascript的slice() 方法
2015/04/20 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
jQuery实现form表单元素序列化为json对象的方法
2015/12/09 Javascript
jQuery插件ajaxFileUpload异步上传文件
2016/10/19 Javascript
快速实现JS图片懒加载(可视区域加载)示例代码
2017/01/04 Javascript
Node+Express+MongoDB实现登录注册功能实例
2017/04/23 Javascript
vue中如何实现变量和字符串拼接
2017/06/19 Javascript
vue.js element-ui tree树形控件改iview的方法
2018/03/29 Javascript
React+Webpack快速上手指南(小结)
2018/08/15 Javascript
vue+element的表格实现批量删除功能示例代码
2018/08/17 Javascript
vue.js使用v-model实现表单元素(input) 双向数据绑定功能示例
2019/03/08 Javascript
vue跳转同一个组件,参数不同,页面接收值只接收一次的解决方法
2019/11/05 Javascript
JavaScript对象属性操作实例解析
2020/02/04 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
JS绘图Flot应用图形绘制异常解决方案
2020/10/16 Javascript
Python基于回溯法子集树模板解决野人与传教士问题示例
2017/09/11 Python
详解django三种文件下载方式
2018/04/06 Python
微软日本官方网站:Microsoft日本
2017/11/26 全球购物
Python中pass语句的作用是什么
2016/06/01 面试题
2014市国税局对照检查材料思想汇报
2014/09/23 职场文书
2014年重阳节老干部座谈会局领导发言稿
2014/09/25 职场文书
出国签证在职证明范本
2014/11/24 职场文书
2016年秋季开学典礼新闻稿
2015/11/25 职场文书
2016年党课培训学习心得体会
2016/01/07 职场文书
Java Socket实现多人聊天系统
2021/07/15 Java/Android
SQL中的三种去重方法小结
2021/11/01 SQL Server
详解Flutter网络请求Dio库的使用及封装
2022/04/14 Java/Android