ホームページ > 記事 > ウェブフロントエンド > Vue2 はコンポーネント props の双方向バインディングを実装します
Vue 学習ノート-3 まえがき
Vue 1.x、Vue 2.x と比較すると、Virtual-Dom の実装に加えて、アップグレードの変更によってユーザーに生じる最大の不快感は、Vue 1.x、Vue 2.x の双方向バインディング機能が削除されたことです。コンポーネントの小道具。
以前は、Vue1 で props の twoWay および .sync バインディング修飾子が使用されていました。
Vue2のコンポーネントpropsの通信方法
Vue2ではコンポーネントpropsのデータフローが一方向の流れのみに変更されました。つまり、propsはコンポーネントの外部(呼び出し側コンポーネント側)からコンポーネント内部へのみ渡せます。コンポーネントは、コンポーネントの DOM 属性属性を通じてコンポーネントの外部から渡されるデータのみを受動的に受け取ることができ、コンポーネント内では、外側の層から渡される props データを変更することはできません。
この変更の公式説明:
prop は一方向のバインディングです。親コンポーネントのプロパティが変更されると、それは子コンポーネントに送信されますが、その逆は行われません。これは、子コンポーネントが親コンポーネントの状態を不注意に変更することを防ぐためです。これにより、アプリケーションのデータ フローが理解しにくくなります。
プロパティの双方向バインディングを放棄することはプロジェクト全体にとって有益で正しいことですが、ある時点でコンポーネント内からプロパティを変更する必要があります
ケース
iOS スタイルのスイッチ ボタンの要件は 2 つだけです:
ボタンをクリックしてオン/オフ状態を切り替えます
ボタンをクリックせずに、カスケードリンク スイッチなどのデータの外部変更を通じてスイッチ状態を切り替えることもできます。
コードは大まかに次のようなものです:
<div id="app"> <!--开关组件--> <switchbtn :result="result"></switchbtn> <!--外部控制--> <input type="button" value="change" @click="change"> </div>
//开关组件代码 Vue.component("switchbtn",{ template:"<div @click='change'>{{result?'开':'关'}}</div>", props:["result"], methods:{ change(){ this.result=!this.result; } } }); //调用组件 new Vue({ el: "#app", data:{ result:true//开关状态数据 }, methods:{ change(){ this.result=!this.result; } } });
しかし、vue2.0では、上記のコードはスイッチをクリックするとエラーを報告します:
[Vue warn]: 値が次のとおりであるため、プロパティを直接変更することは避けてください。親コンポーネントが再レンダリングされるたびに上書きされます。代わりに、変更されるプロパティの値に基づいてデータまたは計算されたプロパティを使用します: "result" (コンポーネント内にあります)
コンポーネント内でプロパティの値を変更することはできません。また、変更された値はコンポーネントの外側の層に同期されません。つまり、呼び出し側コンポーネントはコンポーネント内の現在の状態を知りません。Vue2.0 では、コンポーネントの双方向バインディング メソッドが使用されます。 1. コンポーネントにデータ オブジェクトを作成します。 props 属性のコピー
result は書き込みできないため、data に myResult 変数のコピーを作成する必要があります。初期値は props 属性の結果の値です。同時に、このデータ オブジェクト myResult は、props を呼び出す必要があるコンポーネント内のすべての場所で呼び出されます。
Vue.component("switchbtn", { template: "<div @click='change'>{{myResult?'开':'关'}}</div>", props: ["result"], data: function () { return { myResult: this.result//data中新增字段 }; }, ...... });
2. props属性のwatchを作成し、コンポーネント外のpropsの変更を同期します
このとき、コンポーネントのpropsがコンポーネント外(親コンポーネント)で変更された場合は、コンポーネント内の対応する props ですが、データ オブジェクト内に作成したばかりのコピーに同期されるため、props 属性の結果の監視 (モニター) を作成する必要があります。props が変更されると、対応するコピー myResult が作成されます。データ内の もデータを同期します。
Vue.component("switchbtn", { template: "<div @click='change'>{{myResult?'开':'关'}}</div>", props: ["result"], data: function () { return { myResult: this.result }; }, watch: { result(val) { this.myResult = val;//新增result的watch,监听变更并同步到myResult上 } }, ......
3. props のコピーの監視を作成し、コンポーネントの外部に通知します。
このとき、props のコピー myResult はコンポーネントの外部では認識されません。コンポーネント内のプロパティのステータスを確認するため、データ属性に対応するウォッチである props copy myResult を作成する必要があります。
コンポーネント内の通知を外側の層 (親コンポーネント) に送信して、コンポーネント内のプロパティの変更を通知します。その後、外側の層 (親コンポーネント) がそのデータ自体を変更します 最終的なコード:<div id="app"> <switchbtn :result="result" @on-result-change="onResultChange"></switchbtn> <input type="button" value="change" @click="change"> </div>
Vue.component("switchbtn", { template: "<div @click='change'>{{myResult?'开':'关'}}</div>", props: ["result"], data: function () { return { myResult: this.result//①创建props属性result的副本--myResult }; }, watch: { result(val) { this.myResult = val;//②监听外部对props属性result的变更,并同步到组件内的data属性myResult中 }, myResult(val){ //xxcanghai 小小沧海 博客园 this.$emit("on-result-change",val);//③组件内对myResult变更后向外部发送事件通知 } }, methods: { change() { this.myResult = !this.myResult; } } }); new Vue({ el: "#app", data: { result: true }, methods: { change() { this.result = !this.result; }, onResultChange(val){ this.result=val;//④外层调用组件方注册变更方法,将组件内的数据变更,同步到组件外的数据状态中 } } });
今、コンポーネント内のデータとコンポーネント外のデータの双方向バインディング、およびコンポーネント内外のデータの同期が実装されています。最終的に、これは 1 つの文に要約されます。コンポーネントが内部で変更された場合、それが外部に伝えられ、外部がそれを変更するかどうかを決定します。
4. 双方向バインディングにはどのような小道具が適していますか?最初に宣言することは、特に複雑なビジネスにおいて、双方向バインディング プロパティはコンポーネント間のデータ状態管理には決して役に立たないということです。そのため、双方向バインディングと過度に複雑なデータ処理の使用はできるだけ少なくすることをお勧めします。 Vuex (http://vuex.vuejs.org/zh-cn/intro.html)
しかし、私たちの日常的な使用においては、確かに props の双方向バインディングが必要であると個人的には思います。以下の条件が満たされる場合に使用されます。双方向バインディング プロパティを使用します。
Props はコンポーネント内で変更する必要があります。
コンポーネントは、単に初期化されるのではなく、実行時に外部から動的に制御される必要があります。
コンポーネントの外部は、処理のためにコンポーネント内のステータスを読み取る必要があります
上記の条件を満たすものには、この例の switch コンポーネントが含まれます。これには、スイッチ状態の外部制御が必要です。別の例は、次の activeIndex 属性です。 Tab マルチタブ コンポーネント。現在タブが開いているページなどを外部から制御できる必要があります。
小道具の自動双方向バインディング処理
Vue の mixin コンポーネント - propsync
通过上例也可以看出在Vue2.0中实现props的双向绑定很麻烦,如果有两个props需要做双向绑定上面的代码就要实现两遍,代码极其冗余。
所以我写了一个mixin来自动化处理props的双向绑定的需求——propsync。
主要功能
实现了在组件内自动创建所有prop对应的data属性,方便组件内修改prop使用。解决了vue2.0中不允许组件内直接修改prop的设计。
实现了组件外修改组件prop,组件内自动同步修改到data属性。
实现了组件内修改了data属性(由prop创建的),自动向组件外发出事件通知有内部prop修改。由组件外决定是否要将修改同步到组件外
propsync的使用方法
编写组件
对于编写组件时,如果需要props双向绑定,则直接引入mixin,并在配置中声明mixin即可: mixins: [propsync]
此mixin会根据prop的名称生成对应的data属性名,默认为在prop属性名前面增加"p_",即若prop中有字段名为active,则自动生成名为p_active的data字段(props到data的名称变更方法可自行修改,详见propsync源码开头配置)
propsync默认会将所有props创建双向绑定,可通过propsync:false来声明此props不需要创建双向绑定。
例:
import propsync from './mixins/propsync';//引入mixin文件 export default { name: "tab", mixins: [propsync],//声明使用propsync的mixin props: { active: { type: [String, Number],//会被propsync自动实现双向绑定,在data中创建p_active变量 }, width: { type: [Number, String], propsync:false//不会被propsync实现双向绑定 } }, methods: { setActive(page, index, e) { this.p_active = index;//可以直接使用this.p_active } } }
调用组件
引入propsync后,会在内部双向绑定的data变更后触发一个onPropsChange事件。遂在调用组件处,增加一个事件监听 onPropsChange(可修改),当组件内修改了props时propsync会触发此事件,返回参与依次为:修改prop名称,修改后值,修改前值。可以由当前组件调用方(父组件)来决定是否要将组件内的变更同步到调用方
例:
<tab :active="active" @onPropsChange="change"></tab> ......略 { data:{ active:0 }, methods:{ change:function(propName,newVal,oldVal){ this[propName]=newVal; console.log("组件tab的" +propName+ "属性变更为" +newVal); } } }
更多Vue2 はコンポーネント props の双方向バインディングを実装します相关文章请关注PHP中文网!