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 相关文章推荐
onpropertypchange
Jul 01 Javascript
判断控件是否已加载完成的代码
Feb 24 Javascript
Array.prototype.slice 使用扩展
Jun 09 Javascript
DIV始终居中的js代码
Feb 17 Javascript
jQuery实现不断闪烁文字的方法
May 15 Javascript
js流动式效果显示当前系统时间
May 16 Javascript
JS简单实现tab切换效果的多窗口显示功能
Sep 07 Javascript
layui表格checkbox选择全选样式及功能的实例
Mar 07 Javascript
vue和better-scroll实现列表左右联动效果详解
Apr 29 Javascript
vue-autoui自匹配webapi的UI控件的实现
Mar 20 Javascript
JavaScript实现五子棋小游戏
Oct 26 Javascript
微信小程序将页面按钮悬浮固定在底部的实现代码
Oct 29 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 exif扩展方法开启详解
2014/07/28 PHP
php定义参数数量可变的函数用法实例
2015/03/16 PHP
Laravel 5.4.36中session没有保存成功问题的解决
2018/02/19 PHP
PHP swoole和redis异步任务实现方法分析
2019/08/12 PHP
使用Javascript和DOM Interfaces来处理HTML
2006/10/09 Javascript
Array.prototype.concat不是通用方法反驳[译]
2012/09/20 Javascript
javascript获取网页中指定节点的父节点、子节点的方法小结
2013/04/24 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
2015/07/18 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
2015/12/16 Javascript
javascript回到顶部特效
2016/07/30 Javascript
vue中使用element-ui进行表单验证的实例代码
2018/06/22 Javascript
详解TypeScript+Vue 插件 vue-class-component的使用总结
2019/02/18 Javascript
vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序
2019/07/08 Javascript
微信小程序之下拉列表实现方法解析(附完整源码)
2019/08/23 Javascript
Node.js HTTP服务器中的文件、图片上传的方法
2019/09/23 Javascript
Vue+Node实现商品列表的分页、排序、筛选,添加购物车功能详解
2019/12/07 Javascript
vue过滤器实现日期格式化的案例分析
2020/07/02 Javascript
微信小程序将页面按钮悬浮固定在底部的实现代码
2020/10/29 Javascript
vue.js+element 默认提示中英文操作
2020/11/11 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
2020/11/16 Javascript
js回到页面指定位置的三种方式
2020/12/17 Javascript
Python使用Scrapy保存控制台信息到文本解析
2017/12/27 Python
transform python环境快速配置方法
2018/09/27 Python
详解如何将python3.6软件的py文件打包成exe程序
2018/10/09 Python
Python3爬虫学习之MySQL数据库存储爬取的信息详解
2018/12/12 Python
Python模块的加载讲解
2019/01/15 Python
python numpy之np.random的随机数函数使用介绍
2019/10/06 Python
Python3读写Excel文件(使用xlrd,xlsxwriter,openpyxl3种方式读写实例与优劣)
2020/02/13 Python
Pytorch 扩展Tensor维度、压缩Tensor维度的方法
2020/09/09 Python
python安装第三方库如xlrd的方法
2020/10/31 Python
YSL Beauty加拿大官方商城:圣罗兰美妆加拿大
2017/05/15 全球购物
医院工作检讨书范文
2014/02/10 职场文书
历史学专业求职信
2014/06/19 职场文书
《吃水不忘挖井人》教学反思
2016/02/22 职场文书
关于CSS浮动与取消浮动的问题
2021/06/28 HTML / CSS
为了顺利买到演唱会的票用Python制作了自动抢票的脚本
2021/10/16 Python