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中的prototype与继承
Apr 14 Javascript
用JS将搜索的关键字高亮显示实现代码
Nov 08 Javascript
使用JavaScript的ActiveXObject对象检测应用程序是否安装的方法
Apr 15 Javascript
Node.js的环境安装配置(使用nvm方式)
Oct 11 Javascript
很棒的一组js图片轮播特效
Jan 12 Javascript
vue的状态管理模式vuex
Nov 30 Javascript
JS实现的简单下拉框联动功能示例
May 11 Javascript
axios携带cookie配置详解(axios+koa)
Dec 28 Javascript
利用es6 new.target来对模拟抽象类的方法
May 10 Javascript
react 组件传值的三种方法
Jun 03 Javascript
Vue事件修饰符native、self示例详解
Jul 09 Javascript
分享8个JavaScript库可更好地处理本地存储
Oct 12 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
让这部DC动画新作刷新你的认知
2020/03/03 欧美动漫
IIS环境下快速安装、配置和调试PHP5.2.0
2006/12/17 PHP
发款php蜘蛛统计插件只要有mysql就可用
2010/10/12 PHP
phpize的深入理解
2013/06/03 PHP
php生成图片验证码的实例讲解
2015/08/03 PHP
详解PHP实现异步调用的4种方法
2016/03/14 PHP
PHP MSSQL 分页实例
2016/04/13 PHP
PHP实现登陆表单提交CSRF及验证码
2017/01/24 PHP
对联广告js flash激活
2006/10/19 Javascript
javascript的键盘控制事件说明
2008/04/15 Javascript
jquery选择器的选择使用及性能介绍
2013/01/16 Javascript
鼠标左键单击冲突的问题解决方法(防止冒泡)
2014/05/14 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
2015/09/22 Javascript
node.js 中国天气预报 简单实现
2016/06/06 Javascript
一个超简单的jQuery回调函数例子(分享)
2016/08/08 Javascript
JS与jQuery实现隔行变色的方法
2016/09/09 Javascript
Javascript中判断一个值是否为undefined的方法详解
2016/09/28 Javascript
bootstrap学习使用(导航条、下拉菜单、轮播、栅格布局等)
2016/12/01 Javascript
js实现把时间戳转换为yyyy-MM-dd hh:mm 格式(es6语法)
2017/12/28 Javascript
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
nodejs acl的用户权限管理详解
2018/03/14 NodeJs
vue-cli history模式实现tomcat部署报404的解决方式
2019/09/06 Javascript
JS控制只能输入数字并且最多允许小数点两位
2019/11/24 Javascript
JS如何实现在弹出窗口中加载页面
2020/12/03 Javascript
Python中的random()方法的使用介绍
2015/05/15 Python
Python中将字典转换为XML以及相关的命名空间解析
2015/10/15 Python
python实现三次样条插值
2018/12/17 Python
Python datetime包函数简单介绍
2019/08/28 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
纯CSS3实现绘制各种图形实现代码详细整理
2012/12/26 HTML / CSS
缓解脚、腿和背部疼痛:Z-CoiL鞋
2019/03/12 全球购物
为什么如下的代码int a=100,b=100;long int c=a * b;不能工作
2013/11/29 面试题
社团文化节策划书
2014/02/01 职场文书
八一建军节活动方案
2014/02/10 职场文书
计生个人工作总结
2015/02/28 职场文书
2015年办公室个人工作总结
2015/04/20 职场文书