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 相关文章推荐
利用谷歌地图API获取点与点的距离的js代码
Oct 11 Javascript
jquery map方法使用示例
Apr 23 Javascript
浅谈JavaScript函数节流
Dec 09 Javascript
javascript的列表切换【实现代码】
May 03 Javascript
原生js三级联动的简单实现代码
Jun 07 Javascript
Vue.js中用webpack合并打包多个组件并实现按需加载
Feb 17 Javascript
angular学习之ngRoute路由机制
Apr 12 Javascript
Nuxt.js SSR与权限验证的实现
Nov 21 Javascript
详解Vue 换肤方案验证
Aug 28 Javascript
微信小程序弹窗禁止页面滚动的实现代码
Dec 30 Javascript
动态实现element ui的el-table某列数据不同样式的示例
Jan 22 Javascript
如何用JS实现简单的数据监听
May 06 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中date与gmdate的区别及默认时区设置
2014/05/12 PHP
PHP怎样用正则抓取页面中的网址
2016/08/09 PHP
php检测mysql表是否存在的方法小结
2017/07/20 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
IE6与IE7中,innerHTML获取param的区别
2009/03/15 Javascript
Javascript事件热键兼容ie|firefox
2010/12/30 Javascript
jQuery easyui datagrid动态查询数据实例讲解
2013/02/26 Javascript
jquery click([data],fn)使用方法实例介绍
2013/07/08 Javascript
Table冻结表头示例代码
2013/08/20 Javascript
js控制页面控件隐藏显示的两种方法介绍
2013/10/09 Javascript
jquery事件重复绑定的快速解决方法
2014/01/03 Javascript
checkbox勾选判断代码分析
2014/06/11 Javascript
jQuery自定义动画函数实例详解(附demo源码)
2015/12/10 Javascript
Knockout结合Bootstrap创建动态UI实现产品列表管理
2016/09/14 Javascript
get  post jsonp三种数据交互形式实例详解
2017/08/25 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
axios拦截设置和错误处理方法
2018/03/05 Javascript
js tab栏切换代码实例解析
2019/09/03 Javascript
基于Vue+ElementUI的省市区地址选择通用组件
2019/11/20 Javascript
vue el-table实现自定义表头
2019/12/11 Javascript
Vue+Java+Base64实现条码解析的示例
2020/09/23 Javascript
python 队列详解及实例代码
2016/10/18 Python
Python3.4编程实现简单抓取爬虫功能示例
2017/09/14 Python
python实现输入数字的连续加减方法
2018/06/22 Python
python使用folium库绘制地图点击框
2018/09/21 Python
Django框架模板注入操作示例【变量传递到模板】
2018/12/19 Python
python 计算一个字符串中所有数字的和实例
2019/06/11 Python
浅谈python3中input输入的使用
2019/08/02 Python
基于Python爬取爱奇艺资源过程解析
2020/03/02 Python
django美化后台django-suit的安装配置操作
2020/07/12 Python
简约控的天堂:The Undone
2016/12/21 全球购物
办公文员的工作岗位职责
2013/11/12 职场文书
20年同学聚会感言
2014/02/03 职场文书
我的梦想演讲稿
2014/04/30 职场文书
2015年统计员个人工作总结
2015/07/23 职场文书
java调用Restful接口的三种方法
2021/08/23 Java/Android