【问题标题】:Vue.js - change color for all elements except the element clickedVue.js - 改变所有元素的颜色,除了被点击的元素
【发布时间】:2023-03-12 07:08:01
【问题描述】:

我正在尝试从 jQuery 切换到 Vue.js,但我对此有点坚持。我在页面上有 3 个按钮。当我单击一个按钮时,我希望所有其他按钮将背景颜色更改为绿色,并且单击的按钮将其颜色更改为黑色。

使用 jQuery 只需 2 行代码,但我不知道如何使用 Vue.js 来完成它。 Vue.js 似乎也没有 this 关键字。

另外,在这一点上,我只想应用原始 css background-color 属性而不是应用一个类。

这是我的 jQuery 代码 - 非常简单

<div class="main-content-area">    
  <div class="btn">Click me!</div>
  <div class="btn">Click me!</div>
  <div class="btn">Click me!</div>    
</div>
const Example = new Vue({
  el: '.main-content-area',
  methods: {
    addEventListeners() {
      $(document).ready(function() {
        $(".btn").click(function() {
          $(".btn").css("background-color", "green"); // Make all buttons green
          $(this).css("background-color", "black"); // Make the clicked button black
        });
      });
    }
  },
  mounted: function() {
    this.addEventListeners();
  }
})

使用 Vue.js - 我只能做到这一点......

<div class="main-content-area">    
  <div class="btn" @click="changeColor">Click me!</div>
  <div class="btn" @click="changeColor">Click me!</div>
  <div class="btn" @click="changeColor">Click me!</div>    
</div>
const Example = new Vue({
  el: '.main-content-area',
  methods: {
    changeColor() {
      //  Change color to green for all .btn elements
      //  and change  color for clicked .btn to black
    }
  })

【问题讨论】:

    标签: javascript jquery vue.js


    【解决方案1】:

    这是一种更好的方法,不使用不安全的$root$children

    <template>
      <div class="hello">
        <button class="btn" @click="activeButton = 0" v-bind:style="{'background-color':buttonColor[0]}">Click me!</button>
        <button class="btn" @click="activeButton = 1" v-bind:style="{'background-color':buttonColor[1]}">Click me!</button>
        <button class="btn" @click="activeButton = 2" v-bind:style="{'background-color':buttonColor[2]}">Click me!</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "HelloWorld",
      data() {
        return {
          activeButton: 0
        };
      },
      computed: { 
        buttonColor: function() {
          let result = [];
          for (var i = 0; i< 3; i++){
            if (this.activeButton == i){
              result.push('black');
            } else {
              result.push('green');
            }
          }
    
          return result;
        }
      }
    };
    </script>
    

    演示:https://codesandbox.io/s/8kz9y0rjj9

    您也可以按照@Zoha 的建议将button 包装在一个单独的组件中,但鉴于您没有要求,我没有这样做。这将允许在组件中隐藏buttonColor 实现。

    另外请注意,使用类是更可取和更简洁的方法:不需要丑陋的buttonColor 计算函数。

    <template>
      <div class="hello">
        <button class="btn" @click="activeButton = 0" v-bind:class="{'greenBtn':true, 'blackBtn': activeButton == 0}">Click me!</button>
        <button class="btn" @click="activeButton = 1" v-bind:class="{'greenBtn':true, 'blackBtn': activeButton == 1}">Click me!</button>
        <button class="btn" @click="activeButton = 2" v-bind:class="{'greenBtn':true, 'blackBtn': activeButton == 2}">Click me!</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "HelloWorld",
      data() {
        return {
          activeButton: 0
        };
      },
      }
    };
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
     .greenBtn {
       background-color: green
     }
    
     .blackBtn {
       background-color: black
     }
    </style>
    

    【讨论】:

    • 感谢您分享此@Archeg。这是个好主意。但是你能告诉我为什么我们不应该在 vue 中使用 $root 或 $children。我有几个项目,我用过它们。而且还没有问题:)
    • @Zoha 这个想法是每个组件都不应该知道它正在运行的环境(并且应该什么都不知道),除了明确提供给组件的属性。您的组件隐含要求父组件具有 inactiveAllButtons() 方法。组件是应该在没有上下文的任何地方使用的构建块。如果你的构建块需要一些隐含的规则,它们就不再是组件并且变得更难使用。相反,您应该使用 props$emit()
    • @Zoha 不幸的是,我找不到关于这个的好读文章(我只是很难找到好的读物),但我很确定如果你在这里问一个问题,为什么组件应该对父母一无所知,有人会写一个更好的解释。只需查看$parent 属性文档:vuejs.org/v2/api/#parentUse $parent and $children sparingly - they mostly serve as an escape-hatch. Prefer using props and events for parent-child communication.
    • @Zoha 另外我想指出,这并不意味着您应该立即更改代码。如果它有效 - 它很好。我只是在回答 SO 时尝试遵循最佳做法,因为人们在这里学习,一旦习惯了不好的做法,就很难从人们的脑海中消除
    【解决方案2】:

    为按钮使用组件:

    HTML:

    <div class="main-content-area">
    
        <my-custom-button component-type="my-custom-button" ></my-custom-button>
        <my-custom-button component-type="my-custom-button"></my-custom-button>
        <my-custom-button component-type="my-custom-button"></my-custom-button>
    
    </div>
    

    JavaScript:

    Vue.component("my-custom-button",{
            template : '<div class="btn" :style="buttonStyles" @click="activeThisButton" >Click me!</div>',
    
        data(){
            return {
            isActive : false,
          }
        },
    
        computed : {
            buttonStyles(){
            return {
                backgroundColor : this.isActive  ? 'green' : '',
            }
          }
        },
    
        methods : {
            activeThisButton(){
            // call inactiveAllButtons on parent to deselect all buttons
            this.$root.inactiveAllButtons();
            // active current button
            this.isActive = true;
          }
        }
    })
    
    const Example = new Vue
    ({
    
        el: '.main-content-area',
    
        methods : {
            // filter children and find buttons ( by component-type property )
            // and inactive all .
            inactiveAllButtons(){
            var buttons = this.$children.filter(function(child) {
                return child.$attrs['component-type'] === 'my-custom-button';
            });
            for(var i = 0 ; i < buttons.length ; i++ ){
              buttons[i].isActive = false;
            }
          }
        }
    
    });
    

    jsfiddle demo

    【讨论】:

    • 单击按钮时不会取消选择所有其他按钮。
    • 这是一个非常糟糕的方法。在这种情况下,您需要将状态保留在父组件中,并且永远不要使用$children$root。如果您使用其中任何一个,现在您的组件与包含组件紧密耦合,这打破了 vue.js 作为框架的想法
    • @Archeg 所以我们应该检查父级是否有方法,如果有,调用它。如果您有更好的想法,请发表您的想法
    • @Zoha 抱歉,我仍然认为这不是一个好主意,我真的建议你不要编写使用$children$root 的代码,除非真的 必要的。请看我的回答。
    猜你喜欢
    • 2019-06-25
    • 1970-01-01
    • 2023-02-11
    • 2021-09-20
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    相关资源
    最近更新 更多