Vue データ更新ページが更新されない場合のいくつかの状況と解決策

状況 1: Vue は、インスタンスの作成時にデータに存在しない変数を検出できません

理由: Vue はインスタンスの初期化時に data 内のデータに対してゲッター/セッター変換を実行するため、Vue がリアクティブに変換するには変数がデータ オブジェクトに存在する必要があります。

例えば: 

1
2
3
4
5
new Vue({
   data:{},
   template: '<div>{ {message}}</div>'
})
this .message = 'Hello world!' // `message` 不是响应式的页面不会发生变化

解決:

1
2
3
4
5
6
7
new Vue({
   data: {
     message: '' ,
   },
   template: '<div>{ { message }}</div>'
})
this .message = 'Hello world!'

シナリオ 2: Vue は、データ内のオブジェクトの動的な追加と削除を検出できません。

例えば:

1
2
3
4
5
6
7
8
9
10
new Vue({
   data:{
     obj: {
       id: 1
     }
   },
   template: '<div>{ { obj.message }}</div>'
})
this .obj.message = 'hello' // 不是响应式的
delete this .obj.id       // 不是响应式的

解決:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 动态添加 - Vue.set
Vue.set( this .obj, 'id' , 002)
// 动态添加 - this.$set
this .$set( this .obj, 'id' , 002)
// 动态添加多个
// 代替 Object.assign(this.obj, { a: 1, b: 2 })
this .obj = Object.assign({}, this .obj, { a: 1, b: 2 })
// 动态移除 - Vue.delete
Vue. delete ( this .obj, 'name' )
// 动态移除 - this.$delete
this .$ delete ( this .obj, 'name' )

ケース 3: 変数が配列の場合

インデックスを介して直接変更したり割り当てたりすることはできません。また、配列の長さを変更することもできません。

例えば:

1
2
3
4
5
6
7
8
new Vue({
   data: {
     items: [ 'a' , 'b' , 'c' ]
   }
})
this .items[1] = 'x' // 不是响应性的
this .items[3] = 'd' // 不是响应性的
this .items.length = 2 // 不是响应性的

解決:

1
2
3
4
5
6
7
8
9
10
// Vue.set
Vue.set( this .items, 4, 'd' )
// this.$set
this .$set( this .items, 4, 'd)
// Array.prototype.splice
this.items.splice(indexOfItem, 4, ' d')
//修改长度
this .items.splice(3)

シナリオ 4: インターフェイス データを非同期で取得する。DOM データに変更は見つからない

理由: Vue は DOM の更新時に非同期で実行されます。データ変更をリッスンしている限り、Vue はキューを開き、同じイベント ループ内で発生するすべてのデータ変更をバッファーに入れます。同じウォッチャーが複数回トリガーされた場合、キューにプッシュされるのは 1 回だけです。バッファリング中のこの重複排除は、不必要な計算や DOM 操作を回避するために重要です。次に、次のイベント ループ「ティック」で、Vue はキューをフラッシュし、実際の (重複排除された) 作業を実行します。 Vue は内部的に非同期キューにネイティブの Promise.then、MutationObserver、setImmediate を使用しようとしますが、実行環境がサポートしていない場合は、代わりに setTimeout(function, 0) が使用されます。

例えば:

1
2
3
4
5
6
7
8
9
10
<div id= "example" >{ {message}}</div>
var vm = new Vue({
   el: '#example' ,
   data: {
     message: '123'
   }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
vm.$el.style.color = 'red' // 页面没有变化

解決:

1
2
3
4
5
6
7
8
9
10
11
12
var vm = new Vue({
   el: '#example' ,
   data: {
     message: '123'
   }
})
vm.message = 'new message' // 更改数据
//使用 Vue.nextTick(callback) callback 将在 DOM 更新完成后被调用
Vue.nextTick( function () {
   vm.$el.textContent === 'new message' // true
   vm.$el.style.color = 'red' // 文字颜色变成红色
})

シナリオ 5: ループのネスト レベルが深すぎるため、ビューが更新されません。

ネストが深すぎるとページが更新されなくなる場合があり、その場合はページを強制的に更新することができます。

this.$forceUpdate() は、vue インスタンスに仮想 DOM の再レンダリングを強制します。コンポーネントは再ロードされないことに注意してください。
vue のライフサイクルと組み合わせると、$forceUpdate を呼び出すと、beforeUpdate と updated の 2 つのフック関数のみがトリガーされ、他のフック関数はトリガーされません。
すべての子コンポーネントではなく、インスタンス自体とスロット コンテンツに挿入された子コンポーネントにのみ影響します。

1
2
//官方说如果你现在的场景需要用forceUpdate方法 ,那么99%是你的操作有问题
this .$forceUpdate();

状況 6: ルーティング パラメータが変更されると、ページが更新されない (データが更新されない)

例えば:

1
2
3
4
5
6
7
8
< div id = "app" >
   < ul >
     < li >< router-link to = "/home/foo" >To Foo</ router-link ></ li >   
     < li >< router-link to = "/home/baz" >To Baz</ router-link ></ li >   
     < li >< router-link to = "/home/bar" >To Bar</ router-link ></ li >   
   </ ul >   
   < router-view ></ router-view >
</ div >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Home = {
   template: `<div>{ {message}}</div>`,
   data() {
     return {
       message: this .$route.params.name
     }
   }
}
const router = new VueRouter({
   mode: 'history' ,
     routes: [
     {path: '/home' , component: Home },
     {path: '/home/:name' , component: Home }
   ]
})
new Vue({
   el: '#app' ,
   router
})

上記のコードでは、ルート構築オプションのルートで動的ルート '/home/:name' を設定しました。これらはルーティング コンポーネント Home を共有します。つまり、RouterView を再利用します。

ルートが切り替わった場合、最初のルートに一致するパラメータのみがページに表示され、後でルートが切り替わった場合、メッセージは変わりません。

解決:

1. watch を通じて $route の変更を監視します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const Home = {
   template: `<div>{ {message}}</div>`,
   data() {
     return {
       message: this .$route.params.name
     }
   },
   watch:{
      '$route' : function (){
         this .message = this .$route.params.name
      }
   }
}
...
new Vue({
   el: '#app' ,
   router
})

2. キー属性を <router-view> にバインドして、Vue がそれが異なる <router-view> であると認識できるようにします。

欠点: /home から /user やその他のルートにジャンプする場合、コンポーネントの更新について心配する必要がないため、現時点では key 属性は冗長です。

1
2
3
< div id = "app" >
    < router-view :key = "key" ></ router-view >
</ div >

ケース 7: 変数は代入によって定義されます

Vue には、リアクティブ変数と非リアクティブ変数の 2 種類の変数があります。

バックエンドから取得される変数は通常リアクティブ変数です。つまり、Vue によって変更が監視され、ページに同期されます。これらのリアクティブ変数を変更すると、ページもそれに応じて変更されます。

代入によって定義された変数は通常、非応答変数です。これらの非応答変数を変更すると、Vue はその変更を検出しないため、ページは変更されません。

非反応性変数を反応性変数に変更する必要がある場合は、Vue.set メソッドまたは配列突然変異メソッド (プッシュ、スプライスなど) を使用できます。

例 1: Vue.set(オブジェクト、追加されたキー、属性値)

1
2
3
4
Vue.set
//这个是直接用在Vue身上的。例如: Vue.set(对象,添加的key,属性值”)
//常见于: xx.js文件中
//注意: js文件中,需要引入vue,比如: import Vue from vue

例 2: this.$set(オブジェクト、追加されたキー'、属性値)

1
2
3
this .$set
//这个是用在vm或者vc实例身上的,比如vue文件中,this.$set(对象,添加的key',属性值)
//常见于: xx.vue文件中

データの強制更新: this.$forceUpdate();

おすすめ

転載: blog.csdn.net/jyf_568/article/details/134182625