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 相关文章推荐
javascript 全角转换实现代码
Jul 17 Javascript
js中使用DOM复制(克隆)指定节点名数据到新的XML文件中的代码
Jul 27 Javascript
Jquery的基本对象转换和文档加载用法实例
Feb 25 Javascript
JS数组array元素的添加和删除方法代码实例
Jun 01 Javascript
jquery实现超简洁的TAB选项卡效果代码
Aug 28 Javascript
JavaScript几种数组去掉重复值的方法推荐
Apr 12 Javascript
jquery easyui datagrid实现增加,修改,删除方法总结
May 25 Javascript
JS在一定时间内跳转页面及各种刷新页面的实现方法
May 26 Javascript
jQuery实现的模拟弹出窗口功能示例
Nov 24 Javascript
Vue2.0实现调用摄像头进行拍照功能 exif.js实现图片上传功能
Apr 28 Javascript
微信小程序发送短信验证码完整实例
Jan 07 Javascript
JavaScript定时器设置、使用与倒计时案例详解
Jul 08 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
星际争霸 Starcraft 秘技补丁
2020/03/14 星际争霸
用PHP实现多服务器共享SESSION数据的方法
2007/03/16 PHP
PHP Session 变量的使用方法详解与实例代码
2013/09/11 PHP
php函数实现判断是否移动端访问
2015/03/03 PHP
php检查字符串中是否有外链的方法
2015/07/29 PHP
Laravel学习教程之IOC容器的介绍与用例
2017/08/15 PHP
JS 动态加载脚本的4种方法
2009/05/05 Javascript
让你的网站可编辑的实现js代码
2009/10/19 Javascript
JavaScript对象、属性、事件手册集合方便查询
2010/07/04 Javascript
关于Javascript与iframe的那些事儿
2013/07/04 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
nodejs中使用多线程编程的方法实例
2015/03/24 NodeJs
jQuery监控文本框事件并作相应处理的方法
2015/04/16 Javascript
使用Node.js处理前端代码文件的编码问题
2016/02/16 Javascript
BootStrap的弹出框(Popover)支持鼠标移到弹出层上弹窗层不隐藏的原因及解决办法
2016/04/03 Javascript
JS实现简单的右下角弹出提示窗口完整实例
2016/06/21 Javascript
AngularJS基础 ng-cut 指令介绍及简单示例
2016/08/01 Javascript
jQuery实现拖动效果的实例代码
2017/06/25 jQuery
基于Particles.js制作超炫粒子动态背景效果(仿知乎)
2017/09/13 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
python通过ssh-powershell监控windows的方法
2015/06/02 Python
在win和Linux系统中python命令行运行的不同
2016/07/03 Python
Django使用Mysql数据库已经存在的数据表方法
2018/05/27 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
2020/01/19 Python
如何使用python写截屏小工具
2020/09/29 Python
Python中Yield的基本用法
2020/10/18 Python
python中count函数知识点浅析
2020/12/17 Python
python 基于opencv去除图片阴影
2021/01/26 Python
女士和男士时尚鞋在线购物:Shoespie
2019/02/28 全球购物
九年级政治教学反思
2014/02/06 职场文书
幼教求职信
2014/03/12 职场文书
奥巴马连任演讲稿
2014/05/15 职场文书
班主任寄语2015
2015/02/26 职场文书
经典爱情感言
2015/08/03 职场文书
总经理聘用协议书
2015/09/21 职场文书
利用Redis实现点赞功能的示例代码
2022/06/28 Redis