Previously I asked a question about removing a custom truncate filter in Vue. Please see the question here:
Removing a Vue custom filter on mouseover
However, I neglected to mention that I am using a v-for loop and when I hover over one div, I am noticing that all the divs in the loop are having the same action applied to them. I'm not sure how to target only the div that is being hovered over. Here is my template:
<div id="tiles">
<button class="tile" v-for="(word, index) in shuffled" @click="clickWord(word, index)" :title="word.english">
<div class="pinyin">{{ word.pinyin }}</div>
<div class="eng" @mouseover="showAll = true" @mouseout="showAll = false">
<div v-if="showAll">{{ word.english }}</div>
<div v-else>{{ word.english | truncate }}</div>
</div>
</button>
</div>
And the data being returned:
data(){
return {
currentIndex: 0,
roundClear: false,
clickedWord: '',
matchFirstTry: true,
showAll: false,
}
},
If you know Vue, I would be grateful for advice. Thanks!
Previously I asked a question about removing a custom truncate filter in Vue. Please see the question here:
Removing a Vue custom filter on mouseover
However, I neglected to mention that I am using a v-for loop and when I hover over one div, I am noticing that all the divs in the loop are having the same action applied to them. I'm not sure how to target only the div that is being hovered over. Here is my template:
<div id="tiles">
<button class="tile" v-for="(word, index) in shuffled" @click="clickWord(word, index)" :title="word.english">
<div class="pinyin">{{ word.pinyin }}</div>
<div class="eng" @mouseover="showAll = true" @mouseout="showAll = false">
<div v-if="showAll">{{ word.english }}</div>
<div v-else>{{ word.english | truncate }}</div>
</div>
</button>
</div>
And the data being returned:
data(){
return {
currentIndex: 0,
roundClear: false,
clickedWord: '',
matchFirstTry: true,
showAll: false,
}
},
If you know Vue, I would be grateful for advice. Thanks!
Share Improve this question asked Jul 19, 2017 at 18:27 lnambalnamba 1,7313 gold badges20 silver badges26 bronze badges2 Answers
Reset to default 8In your example, showAll
is being used for each of the buttons generated by the v-for to determine whether or not to show the plete text of the word.english
value. This means that whenever the mouseover
event of any the .eng
class divs fires, the same showAll
property is being set to true for every button.
I would replace the showAll
Boolean value with a showWordIndex
property initially set to null
:
data() {
showWordIndex: null,
},
And then in the template, set showWordIndex
to the index
of the word on the mouseover
handler (and to null
in the mouseleave
handler):
<button v-for="(word, index) in shuffled" :key="index">
<div class="pinyin">{{ word.pinyin }}</div>
<div
class="eng"
@mouseover="showWordIndex = index"
@mouseout="showWordIndex = null"
>
<div v-if="showWordIndex === index">{{ word.english }}</div>
<div v-else>{{ word.english | truncate }}</div>
</div>
</button>
Here's a working fiddle.
Even better would be to make a new ponent to encapsulate the functionality and template of everything being rendered in the v-for
, passing the properties of each word
object to the child ponent as props.
This way, you would still use the showAll
property like you are in your example, but you would define it in the child ponent's scope. So now the showAll
property will only affect the instance of the ponent it's related to.
Below is an example of that:
Vue.ponent('tile', {
template: '#tile',
props: ['pinyin', 'english'],
data() {
return { showAll: false };
},
filters: {
truncate: function(value) {
let length = 50;
if (value.length <= length) {
return value;
} else {
return value.substring(0, length) + '...';
}
}
},
})
new Vue({
el: '#app',
data() {
return {
words: [
{pinyin: 1, english: "really long string that will be cut off by the truncate function"},
{pinyin: 2, english: "really long string that will be cut off by the truncate function"},
{pinyin: 3, english: "really long string that will be cut off by the truncate function"},
{pinyin: 4, english: "really long string that will be cut off by the truncate function"},
],
}
}
})
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.4.1/vue.min.js"></script>
<div id="app">
<tile v-for="word, i in words" v-bind="word" :key="word"></tile>
</div>
<script id="tile" type="x-template">
<button :title="english">
<div class="pinyin">{{ pinyin }}</div>
<div class="eng" @mouseover="showAll = true" @mouseout="showAll = false">
<div v-if="showAll">{{ english }}</div>
<div v-else>{{ english | truncate }}</div>
</div>
</button>
</script>
In order to do this, you can't use a puted property (as I originally suggested in the answer of mine that you linked), since you need to be aware of the context that you are in. That said, you CAN use a filter if you apply a showAll
property to each individual instance. If you declare this up front in your data model, the property will be reactive and you can toggle each item individually on mouseover and mouseout.
template:
<div id="app">
<div id="tiles">
<div class="tile" v-for="(word, index) in shuffled" :title="word.english">
<div class="pinyin">{{ word.pinyin }}</div>
<div class="eng" @mouseover="word.showAll = true" @mouseout="word.showAll = false">
{{ word.english | truncate(word) }}
</div>
</div>
</div>
</div>
js:
new Vue({
el: '#app',
data() {
return {
shuffled: [
{ english: 'here', showAll: false},
{ english: 'are', showAll: false },
{ english: 'there', showAll: false },
{ english: 'words', showAll: false }
],
currentIndex: 0,
roundClear: false,
clickedWord: '',
matchFirstTry: true,
}
},
filters: {
truncate: function(value, word) {
console.log(word)
let length = 3;
if (word.showAll || value.length <= length) return value;
return value.substring(0, length) + '...';
}
},
})
See working JSFiddle
The key is to apply showAll
to each word instance and to then pass that word instance back to the filter so that we can check the value of the showAll property. As long as you declare it up front, Vue's reactivity system handles the rest for you.
Note that in this example it isn't necessary to use two elements with a v-if/else. A single element with a filter works perfectly.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745477125a4629395.html
评论列表(0条)