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 31 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
Dec 17 Javascript
浏览器窗口加载和大小改变事件示例
Feb 27 Javascript
简单了解JavaScript操作XPath的一些基本方法
Jun 03 Javascript
浅析Javascript ES6中的原生Promise
Aug 25 Javascript
JS控制FileUpload的上传文件类型实例代码
Oct 07 Javascript
jQuery实现字符串全部替换的方法【推荐】
Mar 09 Javascript
js实现加载页面就自动触发超链接的示例
Aug 31 Javascript
微信小程序从注册账号到上架(图文详解)
Jul 17 Javascript
vue源码nextTick使用及原理解析
Aug 13 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 Javascript
JavaScript的Set数据结构详解
Feb 18 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判断搜索引擎蜘蛛并自动记忆到文件的代码
2012/02/04 PHP
php中++i 与 i++ 的区别
2012/08/08 PHP
PHP下打开phpMyAdmin出现403错误的问题解决方法
2013/05/23 PHP
php实现表单多按钮提交action的处理方法
2015/10/24 PHP
深入理解PHP内核(一)
2015/11/10 PHP
验证javascript中Object和Function的关系的三段简单代码
2010/06/27 Javascript
腾讯UED 漂亮的提示信息效果代码
2011/09/12 Javascript
基于jquery的代码显示区域自动拉长效果
2011/12/07 Javascript
jquery动态更换设置背景图的方法
2014/03/25 Javascript
JavaScript实现网页截图功能
2014/10/16 Javascript
JQuery限制复选框checkbox可选中个数的方法
2015/04/20 Javascript
Jquery中基本选择器用法实例详解
2015/05/18 Javascript
vue-router 学习快速入门
2017/03/01 Javascript
浅谈react-router HashRouter和BrowserRouter的使用
2017/12/29 Javascript
JS实现验证码倒计时的注册页面
2018/01/02 Javascript
linux 下以二进制的方式安装 nodejs
2020/02/12 NodeJs
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
python2.7删除文件夹和删除文件代码实例
2013/12/18 Python
python网络编程学习笔记(一)
2014/06/09 Python
Django的HttpRequest和HttpResponse对象详解
2018/01/26 Python
python创建文件备份的脚本
2018/09/11 Python
Python Django基础二之URL路由系统
2019/07/18 Python
python 通过视频url获取视频的宽高方式
2019/12/10 Python
Python文件夹批处理操作代码实例
2020/07/21 Python
解决selenium+Headless Chrome实现不弹出浏览器自动化登录的问题
2021/01/09 Python
Ralph Lauren拉夫·劳伦美国官网:带有浓郁美国气息的高品味时装品牌
2017/11/01 全球购物
料理师求职信
2014/01/30 职场文书
招商专员岗位职责
2014/02/08 职场文书
关于环保的建议书400字
2014/03/12 职场文书
读书月活动方案
2014/05/22 职场文书
银行奉献演讲稿
2014/09/16 职场文书
群众路线教育实践活动对照检查材料
2014/09/22 职场文书
个人四风问题原因分析及整改措施
2014/09/28 职场文书
2014年圣诞节寄语
2014/12/08 职场文书
工程质量保证书
2015/05/09 职场文书
道歉短信大全
2015/05/12 职场文书