美文网首页
.sync和$attrs

.sync和$attrs

作者: 成熟稳重的李先生 | 来源:发表于2019-08-27 15:13 被阅读0次

1. sync

我们都知道vue中有单项数据流的概念,即数据只能有父组件传递给子组件,在子组件中,不能修改父组件的数据。如果非要这么做,那么可以在子组件中触发($emit)一个事件,然后再父组件中监听。再然后触发改变,最后又经过props传递至子组件

<body>
  <div id="app">
    <child @add="addOne" :num="count"></child>
  </div>
  <script>
    Vue.component('child', {
      template: `
        <div class="child">
          <button @click="$emit('add')">{{num}}</button>
        </div>
      `,
      props: ['num']
    })
    new Vue({
      el: '#app',
      data: {
        count:0
      },
      methods: {
        addOne() {
          this.count += 1;
        }
      }
    })
  </script>
</body>

以上例子相当简单,如果碰到稍微复杂的改值操作,使用emit这种方式就非常繁琐。这时,.sync就派上用场了。其实它只是emit的语法糖而已,不过,对我们来说,却实实在在的简化了代码。

 <div id="app">
    <child :title.sync="doc.title"></child>  <!--在需要双向绑定的prop后加.sync-->
  </div>
  <script>
    Vue.component('child', {
      template: `
        <div class="child">
          <button @click="doSth">{{title}}</button>
        </div>
      `,
      props: ['title'],
      methods: {
        doSth() {
          this.$emit('update:title', '新标题')  // 固定写法“updata:”+要修改的props
        }
      }
    })
    new Vue({
      el: '#app',
      data: {
        doc: {
          title: '标题'
        }
      }
    })
  </script>
//其实:propName.sync="xxx"就相当于“:propName="xxx" @update:propName="xxx=$event"”,即在父组件模板中监听数据更新事件。

2. $attrs

在使用vue时,如果在父组件模板中,给子组件添加了属性,这些属性一般会自动加在子组件的根元素上,比如:

<div id="app">
    <child abc-def disabled :title.sync="doc.title"></child>  <!--这里,我们添加了“abc-def”和disabled-->
  </div>
  <script>
    Vue.component('child', {
      template: `
        <div class="child">
          <button @click="doSth">{{title}}</button>
        </div>
      `,
      ...
    })
image.png

可以看到,disabled和abc-def默认加在了根元素上。可是如果我们要加在特定元素上呢?比如一个input标签上,我们需要传入placeholder,value,disabled这些属性,并且不能加到根元素上。像这样:

<div id="app">
    <super-input placeholder="输入用户名" title="userName" type="text" v-model="name"></super-input>
  </div>
  <script>
    Vue.component('superInput', {
      template: `
        <div class="ipt">
          <label>用户名:<input ><label>
        </div>
      `
    })

如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false。 ——vue中文文档

注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。
inheritAttrs一般用来配合 $attrs 来完成特殊属性传递。
就拿上边的例子来说,vue会把 placeholder="输入用户名" title="userName" type="text" v-model="name"拆解成一个对象,并且赋值给$attrs:

{
    placeholder: '输入用户名',
    title: 'userName',
    type: 'text',
    value: 'name'     // v-model相当于bind+input,大致就相当于于get和set吧,这里只用bind的值
}
// 然后,子组件中要这样使用
<div id="app">
    <super-input placeholder="输入用户名" title="userName" type="text" v-model="name"></super-input>
  </div>
  <script>
    Vue.component('superInput', {
      inheritAttrs: false,
      template: `
        <div class="ipt">
          <label>用户名:<input v-bind="$attrs" @input="$emit('input', $event.target.value)"></label>  <!--前文解释过了,此处的@input相当于v-model的另一半。$attrs接收了福组件模板传递来的属性,并且转为对象-->
        </div>
      `
    })
    let vm = new Vue({
      el: '#app',
      data: {
        name: 'John'
      }
    })
image.png

属性正确地被绑在了需要绑的元素上(包括value)!

需要注意的是,props和$attrs是互斥的,如果给一个子组件传递了很多属性,如果子组件中没有props,那么这些属性都会出现在子组件的$attrs上,相应的,如果某个属性已经被props接收了,那么attrs上便不存在了

3. $listeners

$listeners$attrs类似,$attrs包含了父组件传递给子组件的所有属性,而$listeners包含了父传给子组件的所有事件

<div id="app">
    <my-button @click="change(111)" @mouseup="change(222)"></my-button>
  </div>
  <script>
    new Vue({
      el: "#app",
      components: {
        "myButton": {
          template: `
            <div>
              <button @click="$listeners.click">点我</button> //只能触发父组件的click
              <button @click="$emit('click')">点我1</button>  //只能触发父组件的click
              <button v-on="$listeners">点我2</button> //相当于 v-on:click="$listeners.click" + v-on:mouseup="$listeners.mouseup"
            </div>
          `,
          mounted() {
            console.log(this.$listeners)
          }
        }
      },
      methods: {
        change(a) {
          alert(a)
        }
      }
    })
  </script>

所以,$listeners可以用来批量触发事件

相关文章

  • .sync和$attrs

    1. sync 我们都知道vue中有单项数据流的概念,即数据只能有父组件传递给子组件,在子组件中,不能修改父组件的...

  • vue .sync $attrs $listener inhe

    sync 修饰符 在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护...

  • Vue2.4+新增属性.sync、$attrs、$listene

    .sync 在vue2.4以前,父组件向子组件传值用props;子组件不能直接更改父组件传入的值,需要通过$emi...

  • Attrs 和 Listeners

    这两个属性是 vue 2.4 版本之后提供的,它简直是二次封装组件或者说写高阶组件的神器。在我们平时写业务的时候免...

  • $attrs和$listeners

    $attrs 属于组件的一个属性,可以获取到父组件传递过来的props数据对于子组件而言,父组件给的数据可以利用p...

  • vue $attrs 和$listener

    $attrs $attrs--继承所有的父组件属性(除了prop传递的属性、class 和 style )inhe...

  • mpvue采坑指北

    自定义组件中 v-bind="$attrs" 和 :value="$attrs.value"不会工作的,但是下面的...

  • Vue3 `inheritAttrs`属性继承与`$attrs`

    $attrs和inheritAttrs用法 $attrs属性解释:包含了父作用域中不作为组件 props 或自定义...

  • 在Vue中使用JSX踩坑指南

    1.组件使用$attrs和$listeners传递参数时: 发现v-bind和v-on都不好用了,因为$attrs...

  • Vue2.4 $attrs、$listeners、inherit

    在开始介绍之前先看下vue官方文档对 $attrs和 $listeners的解释: vm.$attrs包含了父作用...

网友评论

      本文标题:.sync和$attrs

      本文链接:https://www.haomeiwen.com/subject/yfheectx.html