vue雙向繫結盲區

weixin_34148340發表於2019-02-21

使用vue雙向繫結的時候,有時候會遇到沒有檢測到資料變化的情況,以下情況,是需要在平常工作和使用中注意的問題

陣列盲區

vue包含一組觀察陣列變異的方法,使用這些方法也會觸發檢視更新

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

但是受到某些限制,vue無法檢測到以下陣列變動(檢視不會更新)

<template>
    <div>
        <button @click="event">click</button>
        {{items}}
    </div>
</template>

<script>
    export default {
        data() {
            return {
                items: ['a', 'b', 'c']
            }
        },
        methods: {
            event() {
                this.items[1] = 'x' // 不是響應式的
                this.items.length = 2 // 不是響應式的
                console.log(this.items)
            }
        }
    }
</script>
3378249-57935255cc71e119.png
image.png

為了解決這個問題,需要使用$set

<template>
    <div>
        <button @click="event">click</button>
        {{items}}
    </div>
</template>

<script>
    export default {
        data() {
            return {
                items: ['a', 'b', 'c']
            }
        },
        methods: {
            event() {
                // this.items[1] = 'x' 
                // this.items.length = 2 
                this.$set(this.items, 1, 'x')
                this.items.splice(2)
                console.log(this.items)
            }
        }
    }
</script>
3378249-9c215e5615374a24.png
image.png

物件盲區

vue不能檢測物件屬性的新增和刪除

<template>
    <div>
        <button @click="event">click</button>
        {{items}}
    </div>
</template>

<script>
    export default {
        data() {
            return {
                items: {
                    a: 1 // 是響應式的
                }
            }
        },
        methods: {
            event() {
                this.items.b = 2 // 不是響應式的
                console.log(this.items)
            }
        }
    }
</script>
3378249-8ffa13d0a36895a9.png
image.png

這裡有兩種解決方法

  1. 在data宣告時,就給出b: ''的宣告
<template>
    <div>
        <button @click="event">click</button>
        {{items}}
    </div>
</template>

<script>
    export default {
        data() {
            return {
                items: {
                    a: 1 // 是響應式的
                }
            }
        },
        methods: {
            event() {
                this.$set(this.items, 'b', 2) // 是響應式的
                console.log(this.items)
            }
        }
    }
</script>
3378249-8cde69b62c89dd53.png
image.png

當你想新增多個新屬性到某個物件上時,也可以利用Object.assign(),但是不要直接給this.yourObject新增,例如

// 此時也不是響應的
Object.assign(vm.items, {
  c: 3
})

可以直接賦值給原有物件

// 此時是響應式的
this.items = Object.assign({}, this.items, {
  v: 3
})

為什麼不能實現響應式?

https://segmentfault.com/a/1190000015783546

相關文章