Vue2.4+新增属性.sync、$attrs、$listeners的具体使用


Posted in Javascript onMarch 08, 2020

sync

在vue2.4以前,父组件向子组件传值用props;子组件不能直接更改父组件传入的值,需要通过$emit触发自定义事件,通知父组件改变后的值。比较繁琐,写法如下:

//父组件
<template>
 <div class="parent">
  <p>父组件传入子组件的值:{{name}}</p>
  <fieldset>
   <legend>子组件</legend>
   <child :val="name" @update="modify">
   </child>
  </fieldset>
 </div>
</template>

<script>
import Child from './Child'
export default {
 components:{Child},
 data () {
  return {
   name:'linda'
  }
 },
 methods:{
  modify(newVal){
   this.name=newVal
  }
 }
}
</script>

//子组件
<template>
  <label class="child">
    输入框:
    <input :value=val @input="$emit('update',$event.target.value)"/>
  </label>
</template>
<script>
export default {
  props:['val']
}
</script>

vue2.4以后的写法明显舒服许多,上面同样的功能,直接上代码

//父组件
<template>
 <div class="parent">
  <p>父组件传入子组件的值:{{name}}</p>
  <fieldset>
   <legend>子组件</legend>
   <child :val.sync="name">
   </child>
  </fieldset>
 </div>
</template>

<script>
import Child from './Child'
export default {
 components:{Child},
 data () {
  return {
   name:'linda'
  }
 }
}
</script>

//子组件
<template>
  <label class="child">
    输入框:
    <input :value=val @input="$emit('update:val',$event.target.value)"/>
  </label>
</template>
<script>
export default {
  props:['val']
}
</script>

写法上简化了一部分,很明显父组件不用再定义方法检测值变化了。其实只是对以前的$emit方式的一种缩写,.sync其实就是在父组件定义了一update:val方法,来监听子组件修改值的事件。

$attrs

想象一下,你打算封装一个自定义input组件——MyInput,需要从父组件传入type,placeholder,title等多个html元素的原生属性。此时你的MyInput组件props如下:

props:['type','placeholder','title',...]

很丑陋不是吗?$attrs专门为了解决这种问题而诞生,这个属性允许你在使用自定义组件时更像是使用原生html元素。比如:

//父组件
<my-input placeholder="请输入你的姓名" type="text" title="姓名" v-model="name"/>

my-input的使用方式就像原生的input一样。而MyInput并没有设置props,如下

<template>
  <div>
    <label>输入框:</label><input v-bind="$attrsAll" @input="$emit('input',$event.target.value)"/>
  </div>
</template>
<script>
export default {
  inheritAttrs:false,
  computed: {
    $attrsAll() {
      return {
        value: this.$vnode.data.model.value,
        ...this.$attrs
      }
    }
  }
}
</script>

基础扫盲

v-model是v-bind:value和v-on:input的简写,所以在父组件你完全可以直接写 :value="name",@input="val => name = val"。查看文档

疑难

引用下vue的官方api中对$attrs的说明

$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)

比较迷惑的一点是给子组件设置:value="name"相当于给子组件设置props:['value'],所以在MyInput中直接从$attrs获取不到value,需要重新包装$attrsAll,添加value属性。所以子组件还有下面写法,我倾向于这种写法,因为它更优雅

<template>
  <div>
    <label>输入框:</label><input v-bind="$attrs" :value="value" @input="$emit('input',$event.target.value)"/>
  </div>
</template>
<script>
export default {
  inheritAttrs:false,
  props:['value']
}
</script>

$listener

同上面$attrs属性一样,这个属性也是为了在自定义组件中使用原生事件而产生的。比如要让前面的MyInput组件实现focus事件,直接这么写是没用的

<my-input @focus="focus" placeholder="请输入你的姓名" type="text" title="姓名" v-model="name"/>

必须要让focus事件作用于MyInput组件的input元素上,最终的MyInput源码如下:

<template>
  <div>
    <label>输入框:</label><input v-bind="$attrsAll" v-on="$listenserAll"/>
  </div>
</template>
<script>
export default {
  inheritAttrs:false,
  props:['value'],
  computed:{
     $attrsAll() {
      return {
        value: this.value,
        ...this.$attrs
      }
    },
    $listenserAll(){
      return Object.assign(
        {},
        this.$listeners,
        {input:(event) => this.$emit('input',event.target.value)})
    }
  }
}
</script>

到此这篇关于Vue2.4+新增属性.sync、$attrs、$listeners的具体使用的文章就介绍到这了,更多相关Vue2.4 .sync、$attrs、$listeners内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
表单(FORM)的一些实用效果代码
Mar 25 Javascript
javascript 自动填写表单的实现方法
Apr 09 Javascript
js给onclick事件赋值,动态传参数实例解说
Mar 28 Javascript
jQuery操作input值的各种方法总结
Nov 21 Javascript
javascript怎么禁用浏览器后退按钮
Mar 27 Javascript
Bootstrap fileinput组件封装及使用详解
Mar 10 Javascript
React组件生命周期详解
Jul 03 Javascript
JavaScript引用类型Function实例详解
Aug 09 Javascript
通过javascript实现段落的收缩与展开
Jun 26 Javascript
微信小程序实现通讯录列表展开收起
Nov 18 Javascript
Vue Elenent实现表格相同数据列合并
Nov 30 Vue.js
vue 组件基础知识总结
Jan 26 Vue.js
Vue vm.$attrs使用场景详解
Mar 08 #Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
Mar 08 #Javascript
vue-cli点击实现全屏功能
Mar 07 #Javascript
vue全屏事件开发详解
Jun 17 #Javascript
vue实现全屏滚动效果(非fullpage.js)
Mar 07 #Javascript
vue项目使用高德地图的定位及关键字搜索功能的实例代码(踩坑经验)
Mar 07 #Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
Mar 07 #Javascript
You might like
php中禁止单个IP与ip段访问的代码小结
2012/07/04 PHP
PHP中替换换行符的几种方法小结
2012/10/15 PHP
php计算税后工资的方法
2015/07/28 PHP
Yii2框架RESTful API 格式化响应,授权认证和速率限制三部分详解
2016/11/10 PHP
PHP使用xpath解析XML的方法详解
2017/05/20 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
2006/10/17 Javascript
javascript 全角转换实现代码
2009/07/17 Javascript
取选中的radio的值
2010/01/11 Javascript
页面回到顶部的三种实现(锚标记,js)
2012/10/01 Javascript
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
javascript静态页面传值的三种方法分享
2013/11/12 Javascript
jQuery中操控hidden、disable等无值属性的方法
2014/01/06 Javascript
jQuery在iframe中无法弹出对话框的解决方法
2014/01/12 Javascript
文本框文本自动补全效果示例分享
2014/01/19 Javascript
谈谈javascript中使用连等赋值操作带来的问题
2015/11/26 Javascript
微信小程序 Buffer缓冲区的详解
2017/07/06 Javascript
javascript简写常用的12个技巧(可以大大减少你的js代码量)
2020/03/28 Javascript
JS和JQuery实现雪花飘落效果
2017/11/30 jQuery
vue 页面加载进度条组件实例
2018/02/05 Javascript
简单介绍react redux的中间件的使用
2018/04/06 Javascript
js实现开关灯效果
2020/03/30 Javascript
javascript设计模式 ? 单例模式原理与应用实例分析
2020/04/09 Javascript
[50:27]OG vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.26
2018/08/30 DOTA
Python文件夹与文件的操作实现代码
2014/07/13 Python
Python实现的下载8000首儿歌的代码分享
2014/11/21 Python
Python实现检测服务器是否可以ping通的2种方法
2015/01/01 Python
示例详解Python3 or Python2 两者之间的差异
2018/08/23 Python
Python干货:分享Python绘制六种可视化图表
2018/08/27 Python
在Python中pandas.DataFrame重置索引名称的实例
2018/11/06 Python
Python FFT合成波形的实例
2019/12/04 Python
环境科学专业个人求职的自我评价
2013/11/28 职场文书
作风整顿剖析材料
2014/09/30 职场文书
中小学教师继续教育心得体会
2016/01/19 职场文书
go 原生http web 服务跨域restful api的写法介绍
2021/04/27 Golang
面试提问mysql一张表到底能存多少数据
2022/03/13 MySQL