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函数ajax
Aug 20 Javascript
Javascript 鼠标移动上去 滑块跟随效果代码分享
Nov 23 Javascript
javascript实现多级联动下拉菜单的方法
Feb 06 Javascript
jquery 插件实现瀑布流图片展示实例
Apr 03 Javascript
js完美解决IE6不支持position:fixed的bug
Apr 24 Javascript
JS实现的Select三级下拉菜单代码
Aug 20 Javascript
js正则表达式惰性匹配和贪婪匹配用法分析
Dec 26 Javascript
Vue官方文档梳理之全局配置
Nov 22 Javascript
Vue头像处理方案小结
Jul 26 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
Jul 19 Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
Jun 05 Javascript
一分钟学会JavaScript中的try-catch
Dec 14 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
php DOS攻击实现代码(附如何防范)
2012/05/29 PHP
PHP获取日期对应星期、一周日期、星期开始与结束日期的方法
2018/06/22 PHP
IE6下通过a标签点击切换图片的问题
2010/11/14 Javascript
Js使用WScript.Shell对象执行.bat文件和cmd命令
2014/12/18 Javascript
Jquery Ajax xmlhttp请求成功问题
2015/02/04 Javascript
Javascript中this关键字的一些小知识
2015/03/15 Javascript
js+css实现超简洁的二级下拉菜单效果代码
2015/09/07 Javascript
js实现仿qq消息的弹出窗效果
2016/01/06 Javascript
原生JS实现 MUI导航栏透明渐变效果
2017/11/07 Javascript
Vue2.0 slot分发内容与props验证的方法
2017/12/12 Javascript
vue-cli webpack2项目打包优化分享
2018/02/07 Javascript
vue请求本地自己编写的json文件的方法
2019/04/25 Javascript
Vue 中 template 有且只能一个 root的原因解析(源码分析)
2020/04/11 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
2020/07/27 Javascript
Vue循环中多个input绑定指定v-model实例
2020/08/31 Javascript
JS实现简单贪吃蛇小游戏
2020/10/28 Javascript
[02:38]DOTA2超级联赛专访Loda 认为IG世界最强
2013/05/27 DOTA
[06:21]2014DOTA2国际邀请赛 庆祝VG首阶段领跑;B叔为挣牛排半夜整理情报
2014/07/13 DOTA
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
对numpy中的数组条件筛选功能详解
2018/07/02 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
重构Python代码的六个实例
2020/11/25 Python
python用分数表示矩阵的方法实例
2021/01/11 Python
HTML5新增加的功能详解
2016/09/05 HTML / CSS
汉森冲浪板:Hansen Surfboards
2018/05/19 全球购物
恒华伟业笔试面试题
2015/02/26 面试题
法律进社区实施方案
2014/03/21 职场文书
小学生评语大全
2014/04/18 职场文书
2014年九一八事变演讲稿
2014/09/14 职场文书
公司委托书格式范文
2014/10/09 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
亲情作文之母爱
2019/09/25 职场文书
Python实现文本文件拆分写入到多个文本文件的方法
2021/04/18 Python
Java Socket实现Redis客户端的详细说明
2021/05/26 Redis
Python通过loop.run_in_executor执行同步代码 同步变为异步
2022/04/11 Python
Python find()、rfind()方法及作用
2022/12/24 Python