【问题标题】:Dynamically Tally Child Elements by Classname in Vue在 Vue 中按类名动态统计子元素
【发布时间】:2018-11-21 02:50:08
【问题描述】:

我有一个页面,允许用户将图像拖放到预定义的 DIV 中,然后我根据图像的类名计算图像的总值。我要做的是让 vue 从每个外部 div.answer 读取值并获取子图像的类名。

我的源代码是:

<div
    is="box-answers"
    v-for="box in boxes.slice().reverse()"
    v-bind:key="box.id"
    v-bind:level="box.level"
    v-bind:hint="box.hint"
></div>

<script>
Vue.component('box-answers', {
    props: ['level','hint'],
    template: '<div class="droppable answer :id="level" :title="hint"></div>'
});

new Vue({ 
    el: '#mainapp',
    data: {
        boxes: [
            { id: 1, level: 'baselevel-1', hint: 'x 1' },
            { id: 2, level: 'baselevel-2', hint: 'x 20' },
            { id: 3, level: 'baselevel-3', hint: 'x 400' },
            { id: 4, level: 'baselevel-4', hint: 'x 8,000' },
            { id: 5, level: 'baselevel-5', hint: 'x 160,000' }
        ]
    }
</script>

这将转换为以下 HTML(嵌套的 DIV 和 SPAN 是用户可以拖动的条目):

    <div id="baselevel-5" class="droppable answer" title="x 160,000">
      <div><img src="images/line.gif" alt="Five" class="imgfive"></div>
      <span><img src="images/dot.gif" alt="One" class="imgone"></span>
    </div>
    ...
    <div id="baselevel-1" class="droppable answer" title="x 1">
      <span><img src="images/line.gif" alt="One" class="imgone"></span>
    </div>

目前,我有 jQuery/JavaScript 使用以下方法计算点值:

$(function(j) {
var arAnswers = Array(1);
count = 0; //
j("div.answer").each(function( idx ) {
    currentId = j(this).attr('id');
    ones = 0;
    fives = 0;

    if ( j("#" + currentId).children().length > 0 ) {
        ones = j("#" + currentId).children().find("img.imgone").length * 1;
        fives = j("#" + currentId).children().find("img.imgfive").length * 5;
        arAnswers[count] = ones + fives; //Tally box value

        count++;
    }
});
});

我希望 Vue 执行类似的迭代和加法,以返回基于图像类名找到的 1 和 5 的总值。

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    目前,您正在将这个问题作为纯 DOM 操作来处理。如果这是你需要的,那么你可以简单地使用$refs:

    <!-- NOTICE ref -->
    <div ref="boxAnswers"
        is="box-answers"
        v-for="box in boxes.slice().reverse()"
        v-bind:key="box.id"
        v-bind:level="box.level"
        v-bind:hint="box.hint">
    </div>
    

    在您的高级组件中,您将拥有如下功能:

    function calculate() {
        // NOTICE $refs
        const arAnswers = this.$refs.boxAnswers.map((x) => {
    
            // $el is the DOM element
            const once = x.$el.querySelectorAll('img.imgone').length * 1;
            const fives = x.$el.querySelectorAll('img.imgfive').length * 5;
    
            return once + fives
    
        });
    
        return arAnswers;
    
    }
    

    但这不是正确的 Vue 做事方式。 你必须从事件和数据模型的角度来思考(MVVM - 不要碰 DOM。DOM 只是你数据的一种表示模型)。由于您有一个基于拖放的应用程序,因此您必须侦听drag、dragstart、dragend 和其他drag 事件。例如:

    <!-- NOTICE drop event -->
    <div @drop="onDropEnd(box, $event)"
        is="box-answers"
        v-for="box in boxes.slice().reverse()"
        v-bind:key="box.id"
        v-bind:level="box.level"
        v-bind:hint="box.hint">
    </div>
    

    您的onDropEnd 事件处理程序将如下所示:

    function onDrop(box, $event) {
    
        // box - on which box drop is happening
        // $event.data - which image is being dropped
    
        // Verify $event.data is actually the image you are intending
        if ($event.data === 'some-type-image') {
            // Do the counting manipulations here
            // ... remaining code
        }
    
    }
    

    这不是一个完整的代码,因为我不知道其他组件。但它应该可以帮助您找到所需的方向。

    【讨论】:

    • 我对 Vue 还是很陌生,所以虽然我理解为什么你的第一个答案不是真正的方法,但我会使用那个答案,直到我对该语言有更深入的了解。使用$refs 让我看到了很多潜力!
    猜你喜欢
    • 1970-01-01
    • 2018-04-14
    • 2018-11-11
    • 2019-09-02
    • 2020-06-30
    • 2023-03-24
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    相关资源
    最近更新 更多