Vue2.4+新增属性.sync、$attrs、$listeners的具体使用

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单

    我的 github 地址 - vue3.0Study- 阶段学习成果都会建立分支. 新组件 - 新路由 Forms.vue ( 下面仅介绍如何创立, 不进行介绍 ) : <template><div class="form"> <input v-model="message" placeholder="edit me"> <p>Message is: {{ message }}</p>

  • Vue v2.4中新增的$attrs及$listeners属性使用教程

    前言 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex.如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀.Vue 2.4 版本提供了另一种方法,使用 v-bind="$attrs", 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用.之所以要提到这两个属性,是因为两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰. 首先分析以下应用场景: A 组件与 B

  • 浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用

    vue父子组件之间的传值我们都知道使用props和emit,但是祖孙之间的传值在以前,我们都需要子辈作为中间人,当祖辈有值要传递给孙辈时,需要子辈作为中间人把值传递给孙辈,当孙辈想要改变祖辈的值时,需要先emit子辈的方法,然后子辈再emit父辈的方法从而改变祖辈的值,如果是多级组件嵌套的话,那么祖孙辈之间传值,就会变得非常的繁琐,为了解决这个需求,vue2.4版本产生了$attrs,$listeners,inheritAttrs这三个属性. vm.$attrs 官方API vm.$attrs

  • Vue2.4+新增属性.sync、$attrs、$listeners的具体使用

    sync 在vue2.4以前,父组件向子组件传值用props:子组件不能直接更改父组件传入的值,需要通过$emit触发自定义事件,通知父组件改变后的值.比较繁琐,写法如下: //父组件 <template> <div class="parent"> <p>父组件传入子组件的值:{{name}}</p> <fieldset> <legend>子组件</legend> <child :val=&quo

  • vue2之响应式双向绑定,在对象或数组新增属性页面无响应的情况

    目录 vue2响应式双向绑定,在对象或数组新增属性页面无响应 问题描述 解决方法 vue2实现响应式数据 JS中的对象属性 利用Object.defineProperty()进行数据劫持 与标签联动 v-model的实现 总结 vue2响应式双向绑定,在对象或数组新增属性页面无响应 问题描述 vue2 中可以将数据与视图进行绑定,修改 data 对象的属性值将引起对应视图的改变. Vue2的数据视图绑定是通过JS特性这一语法实现,其使用中存在数据属性丢失的这 一 bug,主要针对 对象或数组 属

  • Vue2 监听属性改变watch的实例代码

    效果: 代码: <div id="app2"> <label>幼儿园入学年龄(3-6):</label><input type="number" v-model="child.age"> <button @click="older"> + </button> <button @click="younger"> - </

  • 使用Vue.$set()或者Object.assign()修改对象新增响应式属性的方法

    目录 Vue.$set() Vue.$set()源码 Object.assign() 首先建议先读读Vue官方文档深入响应式原理的介绍,对这一块你的理解会加深很多深入响应式原理 vue代码中,只要在data对象里定义的对象,赋值后,任意一个属性值发生变化,视图都会实时变化 比如下面在data定义了obj对象,mounted里赋值后,(也可以在其他地方赋值)只要obj.a或者obj.b的值改变了,视图会跟着变化 data() { return { obj: {} } }, mounted: { t

  • vue2.0 keep-alive最佳实践

    vue2.0 keep-alive的最佳实践,供大家参考,具体内容如下 1.基本用法 vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗 <keep-alive> <component> <!-- 组件将被缓存 --> </component> </keep-alive> 有时候 可能需要缓存整个站点的所有页面,而页面一般一进去都要触发请求的 在使用keep-alive的情况下 <keep-al

  • 稍微学一下Vue的数据响应式(Vue2及Vue3区别)

    什么是数据响应式 从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom. 换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改. 因此实现数据响应式有两个重点问题: 如何知道数据发生了变化? 如何知道数据变化后哪里需要修改? 对于第一个问题,如何知道数据发生了变化,Vue3 之前使用了 ES5 的一个 API Object.defineProperty Vue

  • Vue2.0 $set()的正确使用详解

    vue2.0 给data对象新增属性,并触发视图更新 如下代码,给 student对象新增 age 属性 data () { return { student: { name: '', sex: '' } } } 众所周知,直接给student赋值操作,虽然可以新增属性,但是不会触发视图更新 mounted () { this.student.age = 24 } 原因是:受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除.因为 Vue.js 在初始化实例时将属性转为 getter

  • Vue3对比Vue2的优点总结

    1.为什么要有vue3 我们使用vue2常常会遇到一些体验不太好的地方,比如: 随着功能的增长,需求的增加,复杂组件的代码越来越难以维护,逻辑混乱,虽然vue2也有一些复用的方法,但是都存在一定的弊端,比如我们常常用的Mixin,特别容易发生命名冲突,暴露出来的变量意图不是很明显,重用到其他组件容易冲突. vue2对于typeScript的支持非常有限,没有考虑到ts的集成. vue3的出现就是为了解决vue2的弊端,其composition API很好的解决了逻辑复用的问题,而且vue3源码就

  • vue2.x数组劫持原理的实现

    接上篇Vue2.x 对象劫持,继续来写数组劫持 实现原理: 1 重新定义原生数组方法push unshift shift pop splice sort reverse 因为这些方法可以修改原数组. 2 拿到原生数组方法 Object.create(Array.prototype) 3 AOP拦截,再执行重写数组方法前,先执行原生数组方法 核心监听Observer代码 // 把data中的数据 都使用Object.defineProperty重新定义 es5 // Object.definePr

随机推荐