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 相关文章推荐
js 实现打印网页中定义的部分内容的代码
Apr 01 Javascript
javascript 延迟加载技术(lazyload)简单实现
Jan 17 Javascript
利用js判断浏览器类型(是否为IE,Firefox,Opera浏览器)
Nov 22 Javascript
使用JavaScript获取电池状态的方法
May 03 Javascript
JavaScript数据类型转换的注意事项
Jul 31 Javascript
angularJS深拷贝详解
Mar 23 Javascript
基于 D3.js 绘制动态进度条的实例详解
Feb 26 Javascript
vue 组件的封装之基于axios的ajax请求方法
Aug 11 Javascript
微信小程序 多行文本显示...+显示更多按钮和收起更多按钮功能
Sep 26 Javascript
JavaScript语句错误throw、try及catch实例解析
Aug 18 Javascript
jquery插件懒加载的示例
Oct 24 jQuery
JavaScript实现前端网页版倒计时
Mar 24 Javascript
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
动漫定律:眯眯眼都是怪物!这些角色狠话不多~
2020/03/03 日漫
经典的PHPer为什么被认为是草根?
2007/04/02 PHP
php遍历所有文件及文件夹的方法深入解析
2013/06/08 PHP
完美解决令人抓狂的zend studio 7代码提示(content Assist)速度慢的问题
2013/06/20 PHP
浅析Apache中RewriteCond规则参数的详细介绍
2013/06/30 PHP
php插入排序法实现数组排序实例
2015/02/16 PHP
PHP使用Redis长连接的方法详解
2018/02/12 PHP
php和vue配合使用技巧和方法
2019/05/09 PHP
详解laravel passport OAuth2.0的4种模式
2019/11/04 PHP
nodejs读取memcache示例分享
2014/01/02 NodeJs
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
2014/07/23 Javascript
js密码强度检测
2016/01/07 Javascript
jQuery获取某天的农历日期并判断是否除夕或新年的方法
2016/03/01 Javascript
JS实现消息来时让网页标题闪动效果的方法
2016/04/20 Javascript
jQuery中使用animate自定义动画的方法
2016/05/29 Javascript
微信小程序中做用户登录与登录态维护的实现详解
2017/05/17 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(上)
2018/04/18 Javascript
vscode 插件开发 + vue的操作方法
2020/06/05 Javascript
Python标准库之随机数 (math包、random包)介绍
2014/11/25 Python
Python复制目录结构脚本代码分享
2015/03/06 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
对Python中Iterator和Iterable的区别详解
2018/10/18 Python
关于python之字典的嵌套,递归调用方法
2019/01/21 Python
Python完成哈夫曼树编码过程及原理详解
2019/07/29 Python
Python vtk读取并显示dicom文件示例
2020/01/13 Python
通过实例解析python创建进程常用方法
2020/06/19 Python
python实现b站直播自动发送弹幕功能
2021/02/20 Python
html5使用html2canvas实现浏览器截图的示例
2017/08/31 HTML / CSS
Skyscanner波兰:廉价航班
2017/11/07 全球购物
商务英语毕业生自荐信范文
2013/11/08 职场文书
西式结婚主持词
2014/03/14 职场文书
优秀教导主任事迹材料
2014/05/09 职场文书
2014年文员工作总结
2014/11/18 职场文书
2015年基层党组织公开承诺书
2015/01/21 职场文书
美丽心灵观后感
2015/06/01 职场文书
2019职场单身人才调研报告:互联网行业单身比例最高
2019/08/07 职场文书