英文:
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 'active' class applied, with all other divs having that class removed.
const listOfElements = document.getElementsByClassName('className');
for (i = 0; i < 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:
<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>
Child Component:
<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>
答案1
得分: 1
你应该有类似这样的代码:
父组件:
<template>
  <Child v-for="(item,index) in children" :key="index" :active="index === currentActiveIndex" @activate="currentActiveIndex = index" />
</template>
<script>
export default
{
  data()
  {
     children: [],
     currentActiveIndex: -1,
  }
}
</script>
子组件:
<template>
  <div :class={active: active}" @click="$emit('activate')">
    ......
  </div>
</template>
<script>
export default
{
  props:
  {
    active:
    {
      type: Boolean,
      default: false
    }
  }
}
</script>
英文:
You should have something like this:
Parent:
<template>
  <Child v-for="(item,index) in children" :key="index" :active="index === currentActiveIndex" @activate="currentActiveIndex = index" />
</template>
<script>
export default
{
  data()
  {
     children: [],
     currentActiveIndex: -1,
  }
}
</script>
Child:
<template>
  <div :class={active: active}" @click="$emit('activate')">
    ......
  </div>
</template>
<script>
export default
{
  props:
  {
    active:
    {
      type: Boolean,
      default: false
    }
  }
}
</script>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论