応答システムのVue
私たちは最初の使用Vueの時間、あなたは例えば、いくつかの魔法を感じるだろう。
<div id="app">
<div>价格:¥{{price}}</div>
<div>总价:¥{{price*quantity}}</div>
<div>折扣后:¥{{totlePriceWithTax}}</div>
</div>
<script>
var vm=new Vue({
el:'#app',
data:(){
price:5.00,//单价
quantity:2//数量
},
computed:{totlePriceWithTax(){
return this.price*this.quantity*1.03
}
}
})
</script>
私はその中で何をすべきかわからないときに私たちは、VUEを使用しています。これは、変更が発生した場合、彼は次のことを行います、価格の価値があまりにもこのフィールドに変更するかどうかを知ることができます。
-
価格の更新]ページの表示値
-
乗算式の合計金額を再計算し、表示を更新
-
リコールtotlePriceWithTax機能、および表示を更新
ここでは、我々はあなたが価格変更の後に知っているか疑問、VUEを持っており、どのような値がそれを更新する必要がありますか?なぜ、変更が必要であるたびにそれを更新するには?どのように私はそれを追跡するのですか?
JavaScriptの通常の動作モード
我々は見に私たちの通常のJavaScriptプログラムに照合この例を参照してください。
let price=5;
let quantity=2;
let total=price*quantity;//计算总价
pice=20;//price字段发生变更之后
console.log(`变化之后的总价:${total}`);
どのくらいこの出力は、それを印刷しますか?私はここには使用ヴューがないので、出力10があるようにしたことは明らかです。
私たちはしばしば更新するために、これらの二つのフィールドの価格や数量で我々はしたい、Vueのに使用し、それは、関連する式を更新し、それに関連する機能が実行されます。
しかし、手続きjavascriptのコードが実際に実行されている場合が許容できないのでこと、応答しません。一度に合計金額を更新するためには、それはまた、アップデートに続く、我々は異なる動作モードとJavaScript言語を聞かせする必要があります。
問題
私たちは今の価格や数量フィールドの更新は、それは、どのように時間に、問題をトータルにも再更新表示経験していますか?
試します
まず、我々は、関連する価格を理解する必要があるとtotleは、次のとおりです。
let total=price*quantity;
その後、価格を更新した後、あなたは、このメソッドを再実行する必要があり、新しい合計を取得する必要があります。その後、価格の変更、再実行するように格納する方法は、その合計値が更新されると、保存されているこの方法を置く場所を持っている必要があります。
我々は再び実行したときに、記録機能、変更バックを試してみていること。
let price=5;
let quantity=2;
let total=0;
let target=null;
//记录函数
target=()=>{
total=price*quantity;
}
record();//后面讲解,记住这个我们后面想要运行的函数
target();//同时,我们执行一遍这个方法
達成したレコード録音機能は非常に簡単です:
let storage=[];//这是要记录函数的地方,就是上面图中椭圆的那个东西
//记录方法的实现,这个时候的target就是我们要记录的方法
function record(){
storage.push(target)
}
我々は戻ってそれを実行することができますので、このステップは、店舗のアップを目指します。今回は、操作のすべての内容を記録した機能を必要としています。その後、我々は彼のカザフスタンを実行します。
function replay(){
storage.forEach((run)=>{
run();
})
}
ここでは、我々はすべてのレコードの内容を横断して、各実行。この時間は、我々のコードは、それを変更することができます。
let price=5;
let quantity=2;
let total=0;
let target=null;
function record(){
storage.push(target)
}
function replay(){
storage.forEach((run)=>{
run();
})
}
target=()=>{
total=price*quantity;
}
record();
target();
console.log(total)// 10
price=20;
replay();
console.log(total)//40
だから我々は、プロセスの記録を実現したが、これは、私たちがクラスがtagertのリスト、再実行するために、すべての時間の必要性が維持していることを、クラスとして維持し、このレコードの内容を置くことができない良い管理ではありませんこのクラスは、通知されます。若者は、火力、先に行ってきました。DEPが別のクラスを維持し、
コードは以下の通りであります:
class Dep{
constructor(){
this.subscribers=[];//维护所有target的列表,在得到通知的时候,全部都会运行
}
depend(){
if(target&&!this.subscribers.includes(target)){
//只有target有方法,并且没有被记录过
this.subscribers.push(target);
}
}
notify(){this.subscribers.forEach((sub)=>{
sub();
})
}
}
このクラスでは、我々はもはや使用ストレージ、加入者がレコードを使用もはやターゲット関数の内容を記録し、この文字を使用しない、使用が異なり、また使用される代替リプレイ、実行するには、この時間を通知し、唯一必要があります。
const dep=new Dep();
let price=5;
let quantity=2;
let total=0;
let target=null;
target=()=>{
total=price*quantity;
}
dep.depend();//记录到subscribers中
target();
console.log(total)// 10
price=20;
dep.notify();//遍历执行所有target,分发内容
console.log(total)//40
私たちはそんなに良く、これらのカプセル化の振る舞いを更新するために、観察するために、無名関数を作成することができます場合は、この方法では、全体のプロセスは、少し良くなるが、それでも非常に冗長に見えます。
若者は、常に衝動的に、我々は先に行ってきました。オリジナルの作成と記録:
target=()=>{
total=price*quantity;
}
dep.depend();//记录到subscribers中
target();
一緒にこのパッケージの内容は、私たちはウォッチャーと呼ばれるという名前の関数をカプセル化し、それをパッケージ化した後、私たちはただコールする必要があります。
watcher(()=>{
total=price*quantity
})
我々はうまくやって、ウォッチャーを実現しています。
function watcher(myFunc){
target=myFunc;//传入的函数赋值
dep.depend();//收集
target();//执行一下
target=null;//重置
}
ここでは、myFuncという、この無名関数を受け、その後、ターゲット属性、コールdep.depend(に割り当てられた後ろウォッチャー機能は、ローカルターゲット加入者は、通話の形でレコードに追加されます)、変数myFuncというを受け付け見ますターゲット、およびリセット。
今、私たちは、このコードを試してみてください上記のコードを組み合わせました:
price=20;
console.log(total);
dep.notify();
console.log(total);
そして、ターゲットが必要な関数に渡すのではなく、グローバル変数として設定されなければならない理由であるという問題があります。私たちは、世間話に戻ってきます。
今、私たちはのDEPクラスを持っていますが、私たちが達成したいことは、各変数は、それに関連付けられた対応するレコードの変更を有する場合、フルである、各変数は独自の発を持っています。この5月Zezheng?
若い人は、物事を恐れていない、先に行ってきました。すべての変数の最初のレッツは一緒に入れ:
let data={
price:5,
quantity:2
}
今、私たちは、各プロパティ(価格と数量が)独自の内部のDEPクラスを持っていることを前提としています。私たちは、ウォッチャー、この機能を実行すると:
wacther(()=>{
total=data.price*data.quantity
})
我々は値data.priceに使用しているので、我々は発価格クラス属性が(dep.depend()を呼び出すことで)記録のサブスクリプション・アレー、上の(ターゲットに保存されている)、それ無名関数を使用することができます願っています。一方data.quantityこの変数は、また訪れてきたので、私は、対応するサブスクリプションの配列に記録されるように願っています:
この時間もdata.priceを使用して他の場所がある場合は、我々はまたのDEPクラスのレコードに対応する匿名関数を載せていきたいと思います。だから、ときにそれに対応し、価格でのDEPコールを通知しますか?価格の割り当てでは、時間の値が変更されます。最後に、我々は起こるしたい旨のです。
10
40
私たちは、データがアクセスされたとき、プロパティが変化したときに、配列に対応するサブスクリプションの配列に格納された匿名関数を実行する機能をサブスクライブするために、対応するターゲット無名関数を格納することが可能であることを願っています。
ソリューション
一見、アクセスは、変更しました。Object.definePropertyから直接マインド、このプロパティは、私たちはgetterとsetter関数を定義することができます。どのようにしてのDEPの組み合わせを示す前に、使用法の下で見て:
let data={price:5,quantity:2};
Object.defineProperty(data,'price',{
get(){
console.log('被访问')
},
set(newVal){
console.log('被修改')
}
});
data.price;//输出:被访问
data.price=20;//输出:被修改
ここでは、実際に取得していないと機能が覆われているため、値の変更を設定します。今、私たちは、値を返す値を更新する時間を設定する時間を取得したいです。それでは、internalValue価格の現在の値を格納する変数を追加してみましょう。
let data={price:5,quantity:2};
let internalValue=data.price;//初始值
Object.defineProperty(data,'price',{
get(){
console.log('被访问');
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal
}
});
total=data.price*data.quantity;//调用get
data.price=20;//调用set
だから我々は、我々はそれをすべてに対処することを、すべてのデータを監視できること:
let data={price:5,quantity:2};
Object.keys(data).forEach((key)=>{
let internalValue=data[key];//初始值
Object.defineProperty(data,key,{
get(){
console.log('被访问');
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal
}
});
})
total=data.price*data.quantity;//调用get
data.price=20;//调用set
すべてのデータが変更されているように、あなたは、最大聴くことができます。それらを結合
total=data.price*data.quantity
このコードが実行されると、それは、getプロパティメソッドに対応する価格をトリガする、我々はのDEP価格は、対応する匿名関数(ターゲット)を覚えて期待することができます。ところで、変更された場合は、セットをトリガーし、その後、我々は、最大保存された属性に対応する、この無名関数を呼び出すことができます。
-
値が再実行の変化した場合に、GET-無名関数を覚えておいてください。
-
保存されたセット - 匿名関数を実行し、対応する値にバインドされた匿名関数が変更されます
DEPクラスは、モードに切り替え:
-
現在のターゲットがdep.dependを呼び出す保存 - アクセス価格
-
価格は変更される場合 - dep.notifyのコールの価格は、ターゲットのすべてを再実行します
最後に、我々はこの一緒に、若い男を入れて、やる遊び人ではない、2つの一気それを下:
let data={price:5,quantity:2};
let target=null;
class Dep{
constructor(){
this.subscribers=[];//维护所有target的列表,在得到通知的时候,全部都会运行
}
depend(){
if(target&&!this.subscribers.includes(target)){
//只有target有方法,并且没有被记录过this.subscribers.push(target);
}
}
notify(){
this.subscribers.forEach((sub)=>{
sub();
})
}
}
Object.keys(data).forEach((key)=>{
let internalValue=data[key];
//初始值Object.defineProperty(data,key,{
get(){
console.log('被访问');
dep.depend();//添加对应的匿名函数target
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal;
dep.notify();//触发对应的储存的函数}
});
})
function watcher(myFunc){
target=myFunc;//传入的函数赋值
target();//执行一下
target=null;//重置
}
watcher(()=>{
data.total=data.price*data.quantity;
})