2017-06-14 100 views
3

当开发一个动态FAQ页面时,在点击问题后显示答案时,遇到了这种奇怪的行为。为什么v-show和v-if立即响应对象中的布尔变化,但不响应数组?

当控制答案的打开/关闭的布尔值存储在对象中时,视图立即更新,并且答案即时显示或隐藏。但是,当它存储在列表中时,只有在以其他方式更新视图之前,才会显示或隐藏答案。

这里有一个小提琴显示问题https://jsfiddle.net/masterofginseng/ffqt9n4y/6/

的HTML

<script src="https://npmcdn.com/vue/dist/vue.js"></script> 
<div id="faq"> 
    <div>This responds immediately</div> 
    <hr> 
    <div v-for="questionObj in questions1"> 
    <div style="cursor: pointer;" @click="questionObj.open = !questionObj.open"> 
     {{ questionObj.question }} 
    </div> 
    <div style="color: blue;" v-show="questionObj.open">{{ questionObj.answer }}</div> 
    </div> 
    <br> 
    <br> 
    <div>This doesn't respond until the view is updated in some other way (ex. by clicking on one of the questions above)</div> 
    <hr> 
    <div v-for="questionarray in questions2"> 
    <div style="cursor: pointer;" @click="questionarray[2] = !questionarray[2]"> 
     {{ questionarray[0] }} 
    </div> 
    <div style="color: blue;" v-show="questionarray[2]">{{ questionarray[1] }}</div> 
    </div> 
</div> 

和JavaScript:

new Vue({ 
    el: "#faq", 
    data: { 
    questions1: [{ 
     question: "How big is it?", 
     answer: "very big", 
     open: false 
    }, { 
     question: "How small is it?", 
     answer: "very small", 
     open: false 
    }], 
    questions2: [ 
     ["How big is it?", "very big", false], 
     ["How small is it?", "very small", false] 
    ] 
    } 
}); 

回答

3

由于在Javascript的限制,Vue公司无法检测值的变化具有此语法的项目:

questionarray[2] = !questionarray[2] 

在这里看到:https://vuejs.org/v2/guide/list.html#Array-Change-Detection

正如上面的链接解释的,你必须使用splice()代替:

questionarray.splice(2, 1, !questionarray[2]) 
0

这是因为list-rendering caveats

尝试这样的:

<script src="https://npmcdn.com/vue/dist/vue.js"></script> 
<div id="faq"> 
    <div>This responds immediately</div> 
    <hr> 
    <div v-for="questionObj in questions1"> 
    <div style="cursor: pointer;" @click="questionObj.open = !questionObj.open"> 
     {{ questionObj.question }} 
    </div> 
    <div style="color: blue;" v-show="questionObj.open">{{ questionObj.answer }}</div> 
    </div> 
    <br> 
    <br> 
    <div>This doesn't respond until the view is updated in some other way (ex. by clicking on one of the questions above)</div> 
    <hr> 
    <div v-for="questionarray in questions2"> 
    <div style="cursor: pointer;" @click="myMethod(questionarray)"> 
     {{ questionarray[0] }} 
    </div> 
    <div style="color: blue;" v-show="questionarray[2]">{{ questionarray[1] }}</div> 
    </div> 
</div> 

脚本

new Vue({ 
    el: "#faq", 
    data: { 
    questions1: [{ 
     question: "How big is it?", 
     answer: "very big", 
     open: false 
    }, { 
     question: "How small is it?", 
     answer: "very small", 
     open: false 
    }], 
    questions2: [ 
     ["How big is it?", "very big", false], 
     ["How small is it?", "very small", false] 
    ] 
    }, 
    methods:{ 
     myMethod(questionArray){ 
     this.$set(questionArray, 2, !questionArray[2]); 
    } 
    } 
}); 

这里是jsFiddle

还是不太详细的版本为莱纳斯·博格说:

<script src="https://npmcdn.com/vue/dist/vue.js"></script> 
<div id="faq"> 
    <div>This responds immediately</div> 
    <hr> 
    <div v-for="questionObj in questions1"> 
    <div style="cursor: pointer;" @click="questionObj.open = !questionObj.open"> 
     {{ questionObj.question }} 
    </div> 
    <div style="color: blue;" v-show="questionObj.open">{{ questionObj.answer }}</div> 
    </div> 
    <br> 
    <br> 
    <div>This doesn't respond until the view is updated in some other way (ex. by clicking on one of the questions above)</div> 
    <hr> 
    <div v-for="questionarray in questions2"> 
    <div style="cursor: pointer;" @click="questionarray.splice(2, 1, !questionarray[2])"> 
     {{ questionarray[0] }} 
    </div> 
    <div style="color: blue;" v-show="questionarray[2]">{{ questionarray[1] }}</div> 
    </div> 
</div>