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 相关文章推荐
一个Action如何调用两个不同的方法
May 22 Javascript
json属性名为什么要双引号(个人猜测)
Jul 31 Javascript
js实现超酷的照片墙展示效果图附源码下载
Oct 08 Javascript
JavaScript驾驭网页-获取网页元素
Mar 24 Javascript
Bootstrap3 多选和单选框(checkbox)
Dec 29 Javascript
javascript实现一个网页加载进度loading
Jan 04 Javascript
解析jquery easyui tree异步加载子节点问题
Mar 08 Javascript
select2 ajax 设置默认值,初始值的方法
Aug 09 Javascript
详解Vue前端生产环境发布配置实战篇
May 07 Javascript
Vue表单控件数据绑定方法详解
Feb 05 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
Aug 04 Javascript
在实例中重学JavaScript事件循环
Dec 03 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 缩略图实现函数代码
2011/06/23 PHP
php根据生日计算年龄的方法
2015/07/13 PHP
PHP实现浏览器中直接输出图片的方法示例
2018/03/14 PHP
PhpStorm配置Xdebug调试的方法步骤
2019/02/02 PHP
thinkphp框架使用JWTtoken的方法详解
2019/10/10 PHP
js获取判断上传文件后缀名的示例代码
2014/02/19 Javascript
自己使用jquery写的一个无缝滚动的插件
2014/04/30 Javascript
node.js中的dns.getServers方法使用说明
2014/12/08 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
2015/10/25 Javascript
理解javascript中的严格模式
2016/02/01 Javascript
js滚动条平滑移动示例代码
2016/03/29 Javascript
学习Node.js模块机制
2016/10/17 Javascript
angular中的cookie读写方法
2017/08/02 Javascript
express express-session的使用小结
2018/12/12 Javascript
浅析JavaScript异步代码优化
2019/03/18 Javascript
关于Js中new操作符的作用详解
2021/02/21 Javascript
[00:58]他们到底在电话里听到了什么?
2017/11/21 DOTA
Django框架中的对象列表视图使用示例
2015/07/21 Python
Python实现屏幕截图的代码及函数详解
2016/10/01 Python
Python实现并行抓取整站40万条房价数据(可更换抓取城市)
2016/12/14 Python
对json字符串与python字符串的不同之处详解
2018/12/19 Python
python自动识别文本编码格式代码
2019/12/26 Python
解析PyCharm Python运行权限问题
2020/01/08 Python
2021年的Python 时间轴和即将推出的功能详解
2020/07/27 Python
创建卫生先进单位实施方案
2014/03/10 职场文书
党员干部承诺书范文
2014/03/25 职场文书
办公室领导干部作风整顿个人整改措施
2014/09/17 职场文书
党员违纪检讨书怎么写
2014/11/01 职场文书
企业与个人合作经营协议书
2014/11/01 职场文书
生日答谢词
2015/01/05 职场文书
生产车间管理制度
2015/08/04 职场文书
大队委员竞选稿
2015/11/20 职场文书
话题作文之学会尊重
2019/12/16 职场文书
SpringBoot2 参数管理实践之入参出参与校验的方式
2021/06/16 Java/Android
Java Spring 控制反转(IOC)容器详解
2021/10/05 Java/Android
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技