使用Vue 3根据动态props切换子元素的类

huangapple go评论52阅读模式
英文:

Using Vue 3 to toggle class of child elements based on dynamic props

问题

以下是您要翻译的内容:

const listOfElements = document.getElementsByClassName('className');
for (i = 0; i < listOfElements.length; i++) {
    //根据特定条件添加/移除元素的类...
}

父组件:

<template>
    <h2>Senate District Map</h2>
    <p>Select a senate district to view more information</p>
    <div>
        <div class="mapContainer">
            
            <SenateDistrict
                :districtNumber="1"
                :width="20.3"
                :marginTop="0"
                :marginLeft="0"
                :currentActive="this.activeSenateDistrict"
                @updateActive="updateActive"
            >
                <svg xmlns="http://www.w3.org/2000/svg" class="district" viewBox="0 0 242.254 177.043">
                    <path id="Path_22" data-name="Path 22" d="M1.714,160.891H5.7v-6.174h92.39l11.585-11.575,13.13,11.19h9.943l8.158,8.151v9.4l4.658,4.655h9.581l12.128-12.119v-4.582l2.341-2.339-26.44-43.492,25-32.315H188.3l4.685-2.908L192.9,70.1h5.9l13.033,5.281,6.118-6.113h16.907l8.11-15.879V45.138H190.039l-5.466-5.462,3.656-12.914L174.618.5H1.714Z" transform="translate(-1.214 0)" stroke-miterlimit="10" stroke-width="1"/>
                </svg>
            </SenateDistrict>
            <SenateDistrict
                :districtNumber="2"
                :width="8.6"
                :marginTop="0"
                :marginLeft="14.8"
                :currentActive="this.activeSenateDistrict"
                @updateActive="updateActive"
            >
                <svg xmlns="http://www.w3.org/2000/svg" class="district" viewBox="0 0 104.24 103.79">
                    <path id="Path_23" data-name="Path 23" d="M184.822.5H287.734l-.12,91.373L271.684,102.8l.435-7.09-3.186-3.184,4.091-4.087-15.133-15.12L253.8,77.4l-7.929-7.921,7.349-14,.048-13.287H198.748l-4.175-3.521,3.62-12.733Z" transform="translate(-183.995 0)"  stroke-miterlimit="10" stroke-width="1"/>
                </svg>  
            </SenateDistrict>
        </div>
    </div>
</template>

<script>
    import SenateDistrict from '../../../components/SenateDistrict.vue';

    export default {
        name: 'SenateDistrictMap',
        components: {
            SenateDistrict
        },
        props: {

        },
        data() {
            return {
                activeSenateDistrict: -1
            }
        },
        methods: {
            updateActive: function (senateDistrictNumber) {
                this.activeSenateDistrict = senateDistrictNumber;
            }

        },
        computed: {

        }
    }
</script>

<style scoped>
    .mapContainer {
        position: relative;
        font-size: 1vw;
        transition: 0.2s;
    }

    .district {
        width: 100%;
        height: 100%;
    }

    .district path {
        pointer-events: auto;
        cursor: pointer;
        transition-duration: .1s;
        transition-timing-function: ease-out;
    }
</style>

子组件:

<template>
    <div
        class="senateDistrict"
        :style="{'width': senateDistrictWidth, 'margin-top': senateDistrictMarginTop, 'margin-left': senateDistrictMarginLeft}"
        :class="[isActive ? 'active' : '']"
        @click="updateActive"
    >
        <slot>

        </slot>
    </div>
</template>

<script>
    export default {
        name: 'SenateDistrict',
        components: {

        },
        props: {
            districtNumber: {
                type: Number,
            },
            width: {
                type: Number,
            },
            marginTop: {
                type: Number,
            },
            marginLeft: {
                type: Number,
            },
            currentActive: {
                type: Number,
            }
        },
        data() {
            return {
                isActive: (this.currentActive === this.districtNumber)
            }
        },
        methods: {
            updateActive: function () {
                this.$emit('updateActive', this.districtNumber);
            },
        },
        computed: {
            senateDistrictWidth: function () {
                return this.width + 'em';
            },
            senateDistrictMarginTop: function () {
                return this.marginTop + 'em';
            },
            senateDistrictMarginLeft: function () {
                return this.marginLeft + 'em';
            },
            updateIsActive: function () {
                this.isActive = (this.currentActive === this.districtNumber)
            }
        }
    }
</script>

<style scoped>
    .senateDistrict {
        position: absolute;
        top: 0em;
        left: 0em;
        pointer-events: none;
        fill: transparent;
        stroke: black; 
        z-index: 4;
    }

    .senateDistrict:hover {
        fill: black;
        stroke: none;
    }

    .senateDistrict.active {
        fill: black;
        stroke: none;
    }
</style>

希望这些翻译对您有所帮助。如果有任何其他问题,请随时提出。

英文:

How can I replicate this JavaScript code in Vue 3 to toggle whether or not a div has a class set or not, based on whether it was recently clicked or not? I only want the div that was most recently clicked to have the &#39;active&#39; class applied, with all other divs having that class removed.

const listOfElements = document.getElementsByClassName(&#39;className&#39;);
for (i = 0; i &lt; listOfElements.length; i++) {
      //remove/add class from element if certain criteria are met...
}

So far, what I've tried is having a Vue emit called when I click on the div to update a value stored in the parent component, which is passed down to the children through a bound prop. Here is my code for the two components:

Parent Component:

&lt;template&gt;
    &lt;h2&gt;Senate District Map&lt;/h2&gt;
    &lt;p&gt;Select a senate district to view more information&lt;/p&gt;
    &lt;div&gt;
        &lt;div class=&quot;mapContainer&quot;&gt;
            
            &lt;SenateDistrict
                :districtNumber=&quot;1&quot;
                :width=&quot;20.3&quot;
                :marginTop=&quot;0&quot;
                :marginLeft=&quot;0&quot;
                :currentActive=&quot;this.activeSenateDistrict&quot;
                @updateActive=&quot;updateActive&quot;
            &gt;
                &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; class=&quot;district&quot; viewBox=&quot;0 0 242.254 177.043&quot;&gt;
                    &lt;path id=&quot;Path_22&quot; data-name=&quot;Path 22&quot; d=&quot;M1.714,160.891H5.7v-6.174h92.39l11.585-11.575,13.13,11.19h9.943l8.158,8.151v9.4l4.658,4.655h9.581l12.128-12.119v-4.582l2.341-2.339-26.44-43.492,25-32.315H188.3l4.685-2.908L192.9,70.1h5.9l13.033,5.281,6.118-6.113h16.907l8.11-15.879V45.138H190.039l-5.466-5.462,3.656-12.914L174.618.5H1.714Z&quot; transform=&quot;translate(-1.214 0)&quot; stroke-miterlimit=&quot;10&quot; stroke-width=&quot;1&quot;/&gt;
                &lt;/svg&gt;
            &lt;/SenateDistrict&gt;
            &lt;SenateDistrict
                :districtNumber=&quot;2&quot;
                :width=&quot;8.6&quot;
                :marginTop=&quot;0&quot;
                :marginLeft=&quot;14.8&quot;
                :currentActive=&quot;this.activeSenateDistrict&quot;
                @updateActive=&quot;updateActive&quot;
            &gt;
                &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; class=&quot;district&quot; viewBox=&quot;0 0 104.24 103.79&quot;&gt;
                    &lt;path id=&quot;Path_23&quot; data-name=&quot;Path 23&quot; d=&quot;M184.822.5H287.734l-.12,91.373L271.684,102.8l.435-7.09-3.186-3.184,4.091-4.087-15.133-15.12L253.8,77.4l-7.929-7.921,7.349-14,.048-13.287H198.748l-4.175-3.521,3.62-12.733Z&quot; transform=&quot;translate(-183.995 0)&quot;  stroke-miterlimit=&quot;10&quot; stroke-width=&quot;1&quot;/&gt;
                &lt;/svg&gt;  
            &lt;/SenateDistrict&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
    import SenateDistrict from &#39;../../../components/SenateDistrict.vue&#39;

    export default {
        name: &#39;SenateDistrictMap&#39;,
        components: {
            SenateDistrict
        },
        props: {

        },
        data() {
            return {
                activeSenateDistrict: -1
            }
        },
        methods: {
            updateActive: function ( senateDistrictNumber ) {
                this.activeSenateDistrict = senateDistrictNumber;
            }

        },
        computed: {

        }
    }
&lt;/script&gt;

&lt;style scoped&gt;
    .mapContainer {
        position: relative;
        font-size: 1vw;
        transition: 0.2s;
    }

    .district {
        width: 100%;
        height: 100%;
    }

    .district path {
        pointer-events: auto;
        cursor: pointer;
        transition-duration: .1s;
        transition-timing-function: ease-out;
    }
&lt;/style&gt;

Child Component:

&lt;template&gt;
    &lt;div
        class=&quot;senateDistrict&quot;
        :style=&quot;{ &#39;width&#39;: senateDistrictWidth, &#39;margin-top&#39;: senateDistrictMarginTop, &#39;margin-left&#39;: senateDistrictMarginLeft }&quot;
        :class=&quot;[ isActive ? &#39;active&#39;: &#39;&#39;]&quot;
        @click=&quot;updateActive&quot;
    &gt;
        &lt;slot&gt;

        &lt;/slot&gt;
    &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
    export default {
        name: &#39;SenateDistrict&#39;,
        components: {

        },
        props: {
            districtNumber: {
                type: Number,
            },
            width: {
                type: Number,
            },
            marginTop: {
                type: Number,
            },
            marginLeft: {
                type: Number,
            },
            currentActive: {
                type: Number,
            }
        },
        data() {
            return {
                isActive: (this.currentActive === this.districtNumber)
            }
        },
        methods: {
            updateActive: function () {
                this.$emit( &#39;updateActive&#39;, this.districtNumber );
            },
        },
        computed: {
            senateDistrictWidth: function () {
                return this.width + &#39;em&#39;;
            },
            senateDistrictMarginTop: function () {
                return this.marginTop + &#39;em&#39;;
            },
            senateDistrictMarginLeft: function () {
                return this.marginLeft + &#39;em&#39;;
            },
            updateIsActive: function () {
                this.isActive = (this.currentActive === this.districtNumber)
            }
        }
    }
&lt;/script&gt;

&lt;style scoped&gt;
    .senateDistrict {
        position: absolute;
        top: 0em;
        left: 0em;
        pointer-events: none;
        fill: transparent;
        stroke: black; 
        z-index: 4;
    }

    .senateDistrict:hover {
        fill: black;
        stroke: none;
    }

    .senateDistrict.active {
        fill: black;
        stroke: none;
    }
&lt;/style&gt;

答案1

得分: 1

你应该有类似这样的代码:

父组件:

&lt;template&gt;
  &lt;Child v-for=&quot;(item,index) in children&quot; :key=&quot;index&quot; :active=&quot;index === currentActiveIndex&quot; @activate=&quot;currentActiveIndex = index&quot; /&gt;
&lt;/template&gt;

&lt;script&gt;
export default
{
  data()
  {
     children: [],
     currentActiveIndex: -1,
  }
}
&lt;/script&gt;

子组件:

&lt;template&gt;
  &lt;div :class={active: active}&quot; @click=&quot;$emit(&#39;activate&#39;)&quot;&gt;
    ......
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default
{
  props:
  {
    active:
    {
      type: Boolean,
      default: false
    }
  }
}
&lt;/script&gt;
英文:

You should have something like this:

Parent:

&lt;template&gt;
  &lt;Child v-for=&quot;(item,index) in children&quot; :key=&quot;index&quot; :active=&quot;index === currentActiveIndex&quot; @activate=&quot;currentActiveIndex = index&quot; /&gt;
&lt;/template&gt;

&lt;script&gt;
export default
{
  data()
  {
     children: [],
     currentActiveIndex: -1,
  }
}
&lt;/script&gt;

Child:

&lt;template&gt;
  &lt;div :class={active: active}&quot; @click=&quot;$emit(&#39;activate&#39;)&quot;&gt;
    ......
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default
{
  props:
  {
    active:
    {
      type: Boolean,
      default: false
    }
  }
}
&lt;/script&gt;

huangapple
  • 本文由 发表于 2023年6月16日 12:24:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486951.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定