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 相关文章推荐
使用JQUERY Tabs插件宿主IFRAMES
Jan 01 Javascript
javascript实现json页面分页实例代码
Feb 20 Javascript
60行js代码实现俄罗斯方块
Mar 31 Javascript
JavaScript实现拖拽网页内元素的方法
Apr 15 Javascript
Jquery简单分页实现方法
Jul 24 Javascript
js滚轮事件兼容性问题需要注意哪些
Nov 15 Javascript
leaflet的开发入门教程
Nov 17 Javascript
Bootstrap 中data-[*] 属性的整理
Mar 13 Javascript
微信小程序出现wx.getLocation再次授权问题的解决方法分析
Jan 16 Javascript
使用原生JS实现火锅点餐小程序(面向对象思想)
Dec 10 Javascript
jQuery实现倒计时功能完整示例
Jun 01 jQuery
JavaScript实现矩形块大小任意缩放
Aug 25 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获取网络上文件
2006/10/09 PHP
微博@符号的用户名提示效果。(想@到谁?)
2010/11/05 Javascript
IE6下出现JavaScript未结束的字符串常量错误的解决方法
2010/11/21 Javascript
js实现鼠标悬浮给图片加边框的方法
2015/01/30 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
JavaScript编写简单的计算器
2015/11/25 Javascript
AngularJS基础 ng-mouseover 指令简单示例
2016/08/02 Javascript
微信小程序 wxapp画布 canvas详细介绍
2016/10/31 Javascript
jQuery弹出窗口打开链接的实现代码
2016/12/24 Javascript
jQuery实现的简单拖动层示例
2017/02/22 Javascript
JavaScript创建对象_动力节点Java学院整理
2017/06/27 Javascript
bootstrap treeview 扩展addNode方法动态添加子节点的方法
2017/11/21 Javascript
Vue按需加载的具体实现
2017/12/02 Javascript
微信小程序使用request网络请求操作实例
2017/12/15 Javascript
jquery实现下载图片功能
2019/07/18 jQuery
使用JS location实现搜索框历史记录功能
2019/12/23 Javascript
微信小程序服务器日期格式化问题
2020/01/07 Javascript
[48:46]完美世界DOTA2联赛PWL S2 SZ vs FTD.C 第二场 11.19
2020/11/19 DOTA
python使用urllib2模块获取gravatar头像实例
2013/12/18 Python
详解python中*号的用法
2019/10/21 Python
python os.path.isfile()因参数问题判断错误的解决
2019/11/29 Python
用python3读取python2的pickle数据方式
2019/12/25 Python
python的setattr函数实例用法
2020/12/16 Python
伦敦一家领先的精品零售商:IRIS Fashion
2019/05/24 全球购物
意大利在线大学图书馆:Libreria universitaria
2019/07/16 全球购物
Guess欧洲官网:美国服饰品牌
2019/08/06 全球购物
Crocs波兰官方商店:女鞋、男鞋、童鞋、洞洞鞋
2019/10/08 全球购物
毕业生自荐书
2013/12/18 职场文书
物流仓储计划书
2014/01/10 职场文书
预备党员承诺书
2014/03/25 职场文书
教师一岗双责责任书
2014/04/16 职场文书
学校欢迎标语
2014/06/18 职场文书
2014年学生会主席工作总结
2014/11/07 职场文书
亚布力滑雪场导游词
2015/02/09 职场文书
少年的你:世界上没有如果,要在第一次就勇敢的反抗
2019/11/20 职场文书
Python查找算法的实现 (线性、二分,分块、插值查找算法)
2022/04/24 Python