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 相关文章推荐
JavaScript高级程序设计(第3版)学习笔记5 js语句
Oct 11 Javascript
Javascript中自动切换焦点实现代码
Dec 15 Javascript
JS获取农历日期具体实例
Nov 14 Javascript
给ListBox添加双击事件示例代码
Dec 02 Javascript
BootStrap中Datetimepicker和uploadify插件应用实例小结
May 26 Javascript
bootstrap制作jsp页面(根据值让table显示选中)
Jan 05 Javascript
vue-cli + sass 的正确打开方式图文详解
Oct 27 Javascript
利用vue开发一个所谓的数独方法实例
Dec 21 Javascript
[原创]js实现保存文本框内容为本地文件兼容IE,chrome,火狐浏览器
Feb 14 Javascript
React中如何引入Angular组件详解
Aug 09 Javascript
js+html实现周岁年龄计算器
Jun 25 Javascript
vue基于Teleport实现Modal组件
May 31 Vue.js
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 MemCached 高级缓存应用代码
2010/08/05 PHP
php搜索文件程序分享
2015/10/30 PHP
PHP 接入微信扫码支付总结(总结篇)
2016/11/03 PHP
IIS 7.5 asp Session超时时间设置方法
2017/04/17 PHP
php实现socket推送技术的示例
2017/12/20 PHP
从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解
2019/04/03 PHP
PHP dirname功能及原理实例解析
2020/10/28 PHP
一个基于jquery的图片切换效果
2010/07/06 Javascript
SWFObject 2.1以上版本语法介绍
2010/07/10 Javascript
取消选中单选框radio的三种方式示例介绍
2013/12/23 Javascript
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
网页收藏夹显示ICO图标(代码少)
2015/08/04 Javascript
牛叉的Jquery——Jquery与DOM对象的互相转换及DOM的三种操作
2015/10/29 Javascript
JavaScript的代码编写格式规范指南
2015/12/07 Javascript
谈谈对JavaScript原生拖放的深入理解
2016/09/20 Javascript
jQuery用FormData实现文件上传的方法
2016/11/21 Javascript
解决vue里碰到 $refs 的问题的方法
2017/07/13 Javascript
详解react关于事件绑定this的四种方式
2018/03/09 Javascript
在Vue项目中使用d3.js的实例代码
2018/05/01 Javascript
Angular4 反向代理Details实践
2018/05/30 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
微信小程序导入Vant报错VM292:1 thirdScriptError的解决方法
2019/08/01 Javascript
Python获取单个程序CPU使用情况趋势图
2015/03/10 Python
Python多线程编程(七):使用Condition实现复杂同步
2015/04/05 Python
使用Python内置的模块与函数进行不同进制的数的转换
2016/03/12 Python
python实时检测键盘输入函数的示例
2019/07/17 Python
python中resample函数实现重采样和降采样代码
2020/02/25 Python
keras实现theano和tensorflow训练的模型相互转换
2020/06/19 Python
英国的领先快速时尚零售商:In The Style
2019/03/25 全球购物
老公保证书范文
2014/04/29 职场文书
企业演讲稿范文大全
2014/05/20 职场文书
单位实习鉴定评语
2015/01/04 职场文书
行政主管岗位职责
2015/02/03 职场文书
心理健康教育主题班会
2015/08/13 职场文书
师德师风心得体会(2016精选篇)
2016/01/12 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书