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 相关文章推荐
客户端静态页面玩分页
Jun 26 Javascript
javascript 动态添加事件代码
Nov 30 Javascript
JavaScript控制table某列不显示的方法
Mar 16 Javascript
详解JavaScript中常用的函数类型
Nov 18 Javascript
jQuery插件imgPreviewQs实现上传图片预览
Jan 15 Javascript
异步加载JS、CSS代码(推荐)
Jun 15 Javascript
js删除Array数组中指定元素的两种方法
Aug 03 Javascript
js实现砖头在页面拖拉效果
Nov 20 Javascript
浅谈Node.js:理解stream
Dec 08 Javascript
在Vue-cli里应用Vuex的state和mutations方法
Sep 16 Javascript
vue 中基于html5 drag drap的拖放效果案例分析
Nov 01 Javascript
详解vue中async-await的使用误区
Dec 05 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利用cookie实现访问次数统计代码
2011/05/19 PHP
PHP面向对象概念
2011/11/06 PHP
深入PHP异步执行的详解
2013/06/03 PHP
浅析php中常量,变量的作用域和生存周期
2013/08/10 PHP
ThinkPHP框架实现session跨域问题的解决方法
2014/07/01 PHP
ThinkPHP中的create方法与自动令牌验证实例教程
2014/08/22 PHP
Symfony2学习笔记之模板用法详解
2016/03/17 PHP
Yii2中hasOne、hasMany及多对多关联查询的用法详解
2017/02/15 PHP
Laravel框架基于ajax和layer.js实现无刷新删除功能示例
2019/01/17 PHP
增强的 JavaScript 的 trim 函数的代码
2007/08/13 Javascript
Mootools 1.2教程 同时进行多个形变动画
2009/09/15 Javascript
JQury slideToggle闪烁问题及解决办法
2011/07/05 Javascript
浅谈Javascript事件处理程序的几种方式
2012/06/27 Javascript
javascript 原型链维护和继承详解
2014/11/26 Javascript
jQuery插件jRumble实现网页元素抖动
2015/06/05 Javascript
ES6入门教程之Iterator与for...of循环详解
2017/05/17 Javascript
SpringMVC+bootstrap table实例详解
2017/06/02 Javascript
bootstrap switch开关组件使用方法详解
2017/08/22 Javascript
解决v-for中使用v-if或者v-bind:class失效的问题
2018/09/25 Javascript
JavaScript实现手机号码 3-4-4格式并控制新增和删除时光标的位置
2020/06/02 Javascript
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
Python实现的根据IP地址计算子网掩码位数功能示例
2018/05/23 Python
win10下tensorflow和matplotlib安装教程
2018/09/19 Python
python绘制简单彩虹图
2018/11/19 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
详解基于Jupyter notebooks采用sklearn库实现多元回归方程编程
2020/03/25 Python
python TCP包注入方式
2020/05/05 Python
纯CSS3实现鼠标滑过按钮动画第二节
2020/07/16 HTML / CSS
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
员工培训邀请函
2014/01/11 职场文书
工作表现自我评价
2014/02/08 职场文书
2014年物流工作总结
2014/11/25 职场文书
委托书的样本
2015/01/28 职场文书
sql server 累计求和实现代码
2022/02/28 SQL Server
剑指Offer之Java算法习题精讲二叉树专项训练
2022/03/21 Java/Android
Nginx如何获取自定义请求header头和URL参数详解
2022/07/23 Servers