[vue3] wacth監視、refで定義された監視データ、reactiveで定義された監視データ、落とし穴の詳細説明

連休後半に入って、まだまだ基礎知識の部分がとても弱いと感じています。
休みを利用してもう一度見直してみましょう

以前に記事を記録しました [vue3 の基本的な知識ポイント - 計算して見る]
. 今日の学習プロセス中に、以前に記録した記事は確かに非常に基本的なものであり、多くの点が十分に詳しく説明されていないことがわかりました。

早速、本題に入りましょう。

ビュー2

vue2 の書き込みメソッドを監視します (vue3 は vue2 の書き込みメソッドと下位互換性があります)

<template>
  <div>
    <h1>当前求和为:{
    
    {
    
    sum}}</h1>
    <button @click="sum++">点我+1</button>
  </div>
</template>

<script >

import {
    
     ref, watch } from 'vue';
export default {
    
    
name:'demo',
watch: {
    
    
  // vue2简单写法
  sum(newVal, oldVal) {
    
    
    console.log('sum的值变化了', newVal, oldVal);
  }
  //vue2完整写法
  sum:{
    
    
    handler(newVal,oldval){
    
    
    console.log('sum的值变化了', newVal, oldVal);
    },
    deep:true,
    immediate:true
  }
},
setup(){
    
    
  let sum = ref(0)
  return {
    
    
    sum
  }
}
}

</script>

ここに画像の説明を挿入します
vue2 の記述方法は vue3 でも使用できますが、混在して使用するとコードスタイルが不統一になり、メンテナンスコストが増加します。そして、私たちは vue2 の記述方法に慣れているだけです。私たちは皆、vue3 の記述方法を使用しています。実際、それはよく知られたプロセスです。vue3 の <script setup> 構文とコンポジション API は依然として非常に人気があります。ゆっくり時間をかけてください。

統合された API は実際には組み込み関数の集合体であり、必要に応じて ref、wacth などの対応する関数を導入できます。

ビュー3

1. ref で定義された単一の応答データをリッスンします。

<template>
  <div>
    <h1>当前求和为:{
    
    {
    
    sum}}</h1>
    <button @click="sum++">点我+1</button>
  </div>
</template>
<script >
import {
    
     ref, watch } from 'vue';
export default {
    
    
name:'demo',
setup(){
    
    
  let sum = ref(0)
  //第一个参数,要监听的数据
  //第二个参数,回调函数,两种写法:箭头函数或者普通函数都可以
  //(在vue3中,wathc的回调函数可以写成箭头函数,因为setup中this是undefined,没有响应式的this上下文)

  //箭头函数写法
  watch(sum,(newVal,oldval)=>{
    
    
    console.log('sum变了',newVal,oldval)
    unde
  })
  // 普通函数写法
    watch(sum,function(newVal,oldval){
    
    
    console.log('sum变了',newVal,oldval)
  })
  return {
    
    
    sum
  }
}

}

2. ref で定義された複数の応答データを監視する

<template>
  <div>
    <h1>当前求和为:{
    
    {
    
    sum}}</h1>
    <button @click="sum++">点我+1</button>
    <h2>当前招呼语:{
    
    {
    
    msg}}</h2>
    <button @click="msg+='wow'">点我打招呼</button>
  </div>
</template>
<script >
import {
    
     ref, watch } from 'vue';
export default {
    
    
name:'demo',
setup(){
    
    
  let sum = ref(0)
  let msg = ref('hello')
//vue2中watch是配置项,只能写一个;vue3中watch是函数,可以调用n次
watch(sum,(newVal,oldVal)=>{
    
    
  console.log('sum变了',newVal,oldVal);
})
watch(msg,(newVal,oldVal)=>{
    
    
  console.log('msg',newVal,oldVal);
})
  return {
    
    
    sum,
    msg
  }
}
}
</script>

この書き方では watch 関数を複数回呼び出すことができますが、もっと簡略化した書き方もあります。

<template>
  <div>
    <h1>当前求和为:{
    
    {
    
     sum }}</h1>
    <button @click="sum++">点我+1</button>
    <h2>当前招呼语:{
    
    {
    
     msg }}</h2>
    <button @click="msg += 'wow'">点我打招呼</button>
  </div>
</template>
<script >
import {
    
     ref, watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
    
    let sum = ref(0);
    let msg = ref("hello");
//第一个参数为数组,第二个参数为回调函数
    watch([sum, msg], (newVal, oldVal) => {
    
    
      console.log("sum或msg变了", newVal, oldVal);
    });
    return {
    
    
      sum,
      msg,
    };
  },
};
</script>

ここに画像の説明を挿入します
ここに画像の説明を挿入します
vue3 watch のパラメータ、3 番目は設定項目です

注: ref で定義されたデータを監視するには deep: true を記述する必要はありません。単純なデータ型には詳細な監視は必要ありません。ref で定義されたオブジェクトは基本的に reactive を呼び出して応答性のオブジェクトにパッケージ化するため、ref で定義されたオブジェクトははデフォルトで有効になっています。

watch(source: WatchSource, cb: WatchCallback, options?: WatchOptions): StopHandle
source: モニタリングのソース (応答データ、計算されたプロパティまたは参照など) cb:
ソースが変更されたときに呼び出されるコールバック関数の
オプション( (オプション): 追加のオプション設定を含むオブジェクトで
、リスニングを停止する関数を返します。

    let sum = ref(0);
    let msg = ref("hello");
    //监听单个
     watch(sum, (newVal, oldVal) => {
    
    
      console.log("sum变了", newVal, oldVal);
    },{
    
    
      immediate:true
    });
   //监听多个

    watch([sum, msg], (newVal, oldVal) => {
    
    
      console.log("sum或msg变了", newVal, oldVal);
    },{
    
    
      immediate:true
    });

3. reactive で定義された単一の応答データのすべての属性を監視する

<template>
  <div>
<h2>姓名:{
    
    {
    
    person.name}}</h2>
<h2>性别:{
    
    {
    
    person.sex}}</h2>
<button @click="person.name+='~'">姓名变了</button>

<button  @click="person.sex+='!'">性别变了</button>
  </div>
</template>
<script >
import {
    
    reactive,watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
    
   
    let person = reactive({
    
    
      name:'莲花',
      sex:'男'
      
    })
        watch(person, (newVal, oldVal) => {
    
    
      console.log("person变了", newVal, oldVal);
    });

    return {
    
    
      person
    };
  },
};
</script>

ここには落とし穴があります。recative で定義された応答データは監視のために watch に渡されます。ここでは oldValue を正しく取得できません。デフォルトでは、watch は応答データ属性の変更のみを追跡できますが、以前の古い値は記録しません。reactive で定義されたデータが深くネストされている場合、それを監視するには vue2 で深い監視を有効にする必要がありますが、vue3 ではこれは必要ありません。
ここに画像の説明を挿入します

<template>
  <div>
<h2>姓名:{
    
    {
    
    person.name}}</h2>
<h2>性别:{
    
    {
    
    person.sex}}</h2>
<h2>工作:{
    
    {
    
    person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import {
    
     ref, reactive,watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
    
    let person = reactive({
    
    
      name:'莲花',
      sex:'男',
      job:{
    
    
        job1:{
    
    
          work:'侦探'
        }
      }      
    })
        watch(person, (newVal, oldVal) => {
    
    
      console.log("person变了", newVal, oldVal);
    });
    return {
    
    
  
      person
    };
  },
};
</script>

reactive で定義されたデータは、強制的に深い監視をオンにします。 deep:false が記述されていても、設定は無効になり、手動で深い監視をオフにすることはできません。 4. reactive で定義された単一のレスポンシブ データ内の属性を監視します
ここに画像の説明を挿入します

このように書いても効果はありません。

<template>
  <div>
<h2>姓名:{
    
    {
    
    person.name}}</h2>
<h2>性别:{
    
    {
    
    person.sex}}</h2>
<h2>工作:{
    
    {
    
    person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import {
    
     ref, reactive,watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
       
    let person = reactive({
    
    
      name:'莲花',
      sex:'男',
      job:{
    
    
        job1:{
    
    
          work:'侦探'
        }
      }      
    })
        watch(person.name, (newVal, oldVal) => {
    
    
      console.log("person.name变了", newVal, oldVal);
    });
    return {
    
      
      person
    };
  },
};
</script>

コンソールにプロンプ​​トが表示されます: この方法ではリッスンできません。リッスンできるのは、ref によって定義された値、または reactive によって生成された応答オブジェクト、または配列のみであり、person.name は応答オブジェクトの属性にすぎません。リアクティブによって生成されたオブジェクト。

ここに画像の説明を挿入します
次に、reactive によって生成された応答オブジェクトのプロパティをリッスンする場合は、次のように記述する必要があります。

まず関数を作成します。関数には戻り値があり、監視したい人は誰でもそれを返すことができます。

<template>
  <div>
<h2>姓名:{
    
    {
    
    person.name}}</h2>
<h2>性别:{
    
    {
    
    person.sex}}</h2>
<h2>工作:{
    
    {
    
    person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import {
    
     ref, reactive,watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
    
    let person = reactive({
    
    
      name:'莲花',
      sex:'男',
      job:{
    
    
        job1:{
    
    
          work:'侦探'
        }
      }      
    })
    watch(
   () => person.name,
  (newValue, oldValue) => {
    
    
    console.log(`person变了 发生了变化: ${
     
     oldValue} -> ${
     
     newValue}`);
  }
    )
    return {
    
      
      person
    };
  },
};
</script>

ここに画像の説明を挿入します
5. reactive で定義された単一の応答データ内の特定の属性を監視する

<template>
  <div>
<h2>姓名:{
    
    {
    
    person.name}}</h2>
<h2>性别:{
    
    {
    
    person.sex}}</h2>
<h2>工作:{
    
    {
    
    person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import {
    
     ref, reactive,watch } from "vue";
export default {
    
    
  name: "demo",
  setup() {
    
    
   
    let person = reactive({
    
    
      name:'莲花',
      sex:'男',
      job:{
    
    
        job1:{
    
    
          work:'侦探'
        }
      }
      
    })
    watch(
    //第一个参数改为数组
    //newValue, oldValue也会变成数组格式
         [ () => person.name,() => person.sex],
         (newValue, oldValue) => {
    
    
         console.log(`person的name或sex变了 `,newValue, oldValue);
       }
    )  
    return {
    
      
      person
    };
  },
};
</script>

ここに画像の説明を挿入します

6. 特殊な場合は、ジョブを監視します。ジョブはオブジェクトです。このように直接記述すると、監視できません。理由は、変更の内容レベルが比較的深いためです。変更したいのは、ジョブのジョブ1のジョブ。

   let person = reactive({
    
    
      name:'莲花',
      sex:'男',
      job:{
    
    
        job1:{
    
    
          work:'侦探'
        }
      }
      
    })
    watch(
          () => person.job,
         (newValue, oldValue) => {
    
    
         console.log(`person的job变了 `,newValue, oldValue);
       }
    )  

このとき、設定項目の奥深くまで設定する必要があります。

      watch(
          () => person.job,
         (newValue, oldValue) => {
    
    
         console.log(`person的job变了 `,newValue, oldValue);
       },{
    
    deep:true}
    )  

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/weixin_49668076/article/details/133443463