Vue vm.$atrs使用シーン詳細

11246 ワード

1、vm.$atrs概要
まず、私達はvueの公式対vm.$atrsの紹介を見にきました。
親作用領域にpropとして識別されない(かつ取得される)特性バインディング(classとstyleを除く)が含まれています。一つのコンポーネントがどのようなプロモーションを宣言していない場合、ここにはすべての親作用ドメインのバインディング(classとstyleを除く)が含まれ、v-bind=「$atrs」を介して内部コンポーネントに入ることができます。
ちょっと見ただけでは分かりません。
2、シーン紹介
vueの中の一つの悩み事は、属性が親のコンポーネントからサブコンポーネントにしか渡さないことです。これは、入れ子の階層に対して深いコンポーネントのデータを転送するには、親のコンポーネントからサブコンポーネントにしか渡されず、サブコンポーネントは孫のコンポーネントに再伝達されるという意味である。

<parent-component :passdown="passdown">

<child-component :passdown="passdown">

<grand-child-component :passdown="passdown">

....

このように1階1階の下にpassdownという変数を伝達して、最後にようやく{passdown}を使うことができます。
もし私たちが伝達したい属性は1,2個だけならいいですが、もしいくつかまたは10個の状況が伝達されたら、どのようなシーンになりますか?私たちは各部品のプロpsで、それぞれ何回も書かなければなりません。他に便利な書き方がありますか?あります。vuexの親子コンポーネントを通して通信するのは確かにこれが一つの方法ですが、他の方法があります。これは私達が言いたいのです。inheitAttrsオプションによると、インスタンスプロパティ$atrs
3、例:

<template>
 <div class="home">
  <mytest :title="title" :massgae="massgae"></mytest>
 </div>
</template>
<script>
export default {
 name: 'home',
 data () {
  return {
   title:'title1111',
   massgae:'message111'
  }
 },
 components:{
  'mytest':{
   template:`<div>   h1  {{title}}</div>`,
   props:['title'],
   data(){
    return{
     mag:'111'
    }
   },
   created:function(){
    console.log(this.$attrs)//    
   }
  }
 }
}
</script>
上のコードはコンポーネントの中でtitleという属性だけを使っていますが、masgae属性は役に立たないです。ブラウザで描画するのはどうですか?次の図のように

コンポーネント内に登録されていない属性は普通のhtml要素属性としてレンダリングされますが、もし属性を下に転送したいなら、たとえpropコンポーネントが使用されていなくても、コンポーネントに登録する必要があります。このようにするとコンポーネントの予期機能がぼやけてしまい、コンポーネントのDRYを維持するのも難しいです。Vue 2.4.0では、コンポーネント定義にinhers Attrs:falseを追加することができ、コンポーネントは登録されていないpropsを通常のHTML属性として提示しない。しかし、コンポーネントの中では、私たちは$atrsを通じて、未使用の登録属性を取得することができます。必要であれば、私たちはこれからも転送し続けます。
もし私たちがサブアセンブリにinheitAttrsを設定すると:false:

components:{
  'mytest':{
   template:`<div>   h1  {{title}}</div>`,
   props:['title'],
   inheritAttrs: false,
   data(){
    return{
     mag:'111'
    }
   },
   created:function(){
    console.log(this.$attrs)//    
   }
  }
レンダリング効果は以下の通りです。

引き継がない場合.png
補足:言ってください。
ページがあります。親のセット、子供のセット、孫のセットで構成されています。

<template>
  <div style="padding:50px;">
    <childcom :name="name" :age="age" :sex="sex"></childcom>
  </div>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      template:`<div>
        <div>{{name}}</div>
        <grandcom v-bind="$attrs"></grandcom>
      </div>`,
      props:['name'],
      components: {
        'grandcom':{
          template:`<div>{{$attrs}}</div>`,
        }
      }
    }
  }
}
</script>
上のコードのページでの効果は以下の図です。

サブアセンブリchildcomにatrsを結び付けたら、孫のセットgrandcomからthis.$atrsの値を得ることができます。この{atrs}の値は、親コンポーネントから伝達されるプロpsである。
孫のセットgrandcomからthis.$atrsの値を得たことを覚えてください。サブアセンブリchildcom声明の要素を除いてです。サブアセンブリchildcom声明の要素を除いて覚えてください。たとえば上のコードはサブアセンブリchildcomのpropsでnameを宣言しましたが、孫のコンポーネントgrandcomで取得した$atrsはname属性を含んでいません。
ちょっと言ってください。atrsの優勢はどこにありますか?
もし私たちがページを作るなら、親のセット、子供のセット、孫のセットがあります。

<template>
  <div>
    <childcom></childcom>
  </div>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      template:`<div>
        <div>     </div>
        <grandcom></grandcom>
      </div>`,
      components: {
        'grandcom':{
          template:`<div>      </div>`,
        }
      }
    }
  }
}
</script>
このようなコードの場合、サブアセンブリで親コンポーネントのname属性値を取得したい場合、孫コンポーネントで親コンポーネントのage属性値を取得し、propsを利用すると、親コンポーネントでnameとageの値をpropsを通じてサブアセンブリに伝達しなければならない。サブアセンブリはpropsを通じて、ageの値を孫のコンポーネントに伝達し、ここで分かります。孫のコンポーネントに必要なageはサブアセンブリでは使用されていませんが、孫のコンポーネントを取得するためには、親のコンポーネントからサブアセンブリに伝え、サブアセンブリで孫のコンポーネントに渡す必要があります。
しかし、$atrsを使うのはそんなに面倒ではありません。

<template>
  <div>
    <childcom :name="name" :age="age" :sex="sex"></childcom>
  </div>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      props:['name'],
      template:`<div>
        <div>       {{name}}</div>
        <grandcom v-bind="$attrs"></grandcom>
      </div>`,
      components: {
        'grandcom':{
          template:`<div>      {{$attrs.age}}</div>`,
        }
      }
    }
  }
}
</script>
サブコンポーネントは「$atrs」を結合しています。孫コンポーネントはname属性以外のすべての親コンポーネントから渡される属性を取得できます。孫のコンポーネントもname属性を取得したいなら、バインディングしたnameは以下の通りです。

 <grandcom v-bind="$attrs" :name="name"></grandcom>
この道理かどうか詳しく体得する。どうしてもだめなら、コードを押して自分で試してみてください。
補足します。inheitAttrs属性
inheitAttrsという属性は$atrsの値を取得することに関係なく、inhers Attrsは基本的なコンポーネントを作成する時に使用されます。公式サイトの原語:デフォルトでは父の役割領域のプロpsとして認識されていない特性バインディングは「キャンセル」され、普通のHTML特性としてサブアセンブリのルート要素に適用されます。ターゲット要素または他のコンポーネントを包むコンポーネントを作成すると、これは常に予期された挙動に一致しないかもしれない。inhers Attrsをfalseに設定することで、これらのデフォルトは削除されます。これらの特性は、(2.4で追加されたものと同じ)実例的な属性によって有効になり、v−bind明示的なバインディングによって非ルート要素に結合され得る。
このオプションはclassとstyleの結合に影響しません。
Vue 2.4.0以前のバージョンでは、コンポーネント内に登録されていない属性は、通常のhtml要素属性としてレンダリングされます。
inheitAttrsはいったい何の役に立つのですか?いったいどこに使いますか?下のコードを見てください

<template>
  <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      props:['name','age'],
      template:`<input type="number" style="border:1px solid blue">`,
    }
  }
}
</script>
上のコードはinputにどう表示されると思いますか?父のコンポーネントはtype="text"を伝えていますが、サブコンポーネントのinput上のtype="number"は、ページにレンダリングするのはどうなりますか?レンダリングは以下の通りです

デフォルトの状況.png
見ましたか?父のコンポーネントのtype="text"はinput上のtype="number"をカバーしています。これは私のinputデータのタイプを全部変えたのではないですか?これは問題があるのではないですか?ここを見て分かりましたか?後で上の公式サイトの原語を体得します!!!
需要:input上のtype="number"タイプは不変ですが、私はやはり父のコンポーネントのtype="text"の値を取りたいです。コードは以下の通りです。

<template>
  <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      inheritAttrs:false,
      props:['name','age'],
      template:`<input type="number" style="border:1px solid blue">`,
      created () {
        console.log(this.$attrs.type)
      }
    }
  }
}
</script>
ページレンダリングは以下の通りです。

需要.png
ここまで来て、inheitAttrsの役割は皆さんも分かりましたよね。デフォルトでは、vueは親の役割領域のプロpsとは認められない特性をバインドし、通常のHTML特性としてサブアセンブリのルート要素に適用します。バインディングはバインディングして、表示して、大したことはないですが、上のinputのような特殊な状況に出会うのが怖いです。この時inheitAttrs:falseの役割が出ます。
ついでに補充してください。
父のコンポーネント-子のコンポーネント-孫のコンポーネント、、、今は孫のコンポーネントの中で父のコンポーネントの値を変えたいですが、どうやって変えますか?いろいろな方法がありますが、listenersは私たちに新しい考えを提供してくれました。話を多くしないで、直接コードをかけます。

<template>
  <div>
    <childcom :name="name" :age="age" :sex="sex" @testChangeName="changeName"></childcom>
  </div>
</template>
<script>
export default {
  'name':'test',
  props:[],
  data(){
    return {
      'name':'  ',
      'age':'30',
      'sex':' '
    }
  },
  components:{
    'childcom':{
      props:['name'],
      template:`<div>
        <div>       {{name}}</div>
        <grandcom v-bind="$attrs" v-on="$listeners"></grandcom>
      </div>`,
      
      components: {
        'grandcom':{
          template:`<div>      -------<button @click="grandChangeName">    </button></div>`,
          methods:{
            grandChangeName(){
              this.$emit('testChangeName','kkkkkk')
            }
          }
        }
      }
    }
  },
  methods:{
    changeName(val){
      this.name = val
    }
  }
}
</script>
ページレンダリングは以下の通りです。

$listenersは孫のセットで父のセットの値を変えてもいいですか?便利ですか?
ここでvm.$atrsの使用シーンについて詳しく説明した文章を紹介します。もっと関連したvm.$atrsの使用内容は以前の文章を検索してください。または下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。