【问题标题】:Adding active class to anchor tags将活动类添加到锚标签
【发布时间】:2020-12-22 07:47:30
【问题描述】:

我一直在尝试将.active 类添加到当前链接,并且我知道这里之前有人问过它,但是似乎没有一个答案完全符合我的需要。

这是一个 Vue 组件。我不想添加 vue-router。我想将活动类动态添加到单击的任何链接。

<template>
  <nav>
    <ul>
      <li v-for="(item, $index) in items" :key="$index" >
        <a :href="item.link">{{ item.name }}</a>     //how do I dynamically add the active class here?
      </li>
    </ul>
  </nav>
</template>

<script>
export default {
  name: "Navbar",
  props: {
    items: {
      type: Array,
      default: null,
    },
  },
}
</script>

<style>
 ul li .active {
   background-color: red;
   cursor: pointer;
 }
</style>

链接列表:

const items = [
  {
    name: "Home",
    link: "#home",
  },
  { 
    name: "About", 
    link: "#about" 
  },
  {
    name: "Contacts",
    link: "#contact",
  },
];

【问题讨论】:

    标签: javascript css vue.js vuejs2


    【解决方案1】:

    你可以利用hashchange事件和Vue的class binding:

    <template>
        <nav>
            <ul>
                <li v-for="(item, $index) in items" :key="$index">
                    <a :href="item.link" :class="{ active: hash === item.link }">{{ item.name }}</a>
                </li>
            </ul>
        </nav>
    </template>
    
    <script>
    export default {
        name: 'Navbar',
    
        props: {
            items: {
                type: Array,
                default: null,
            },
        },
    
        data() {
            return {
                hash: window.location.hash,
            };
        },
    
        created() {
            window.addEventListener('hashchange', () => {
                this.hash = window.location.hash;
            });
        },
    };
    </script>
    
    <style>
    ul li .active {
        background-color: red;
        cursor: pointer;
        font-weight: bold;
    }
    </style>
    

    另一种解决方案是使用click 事件和setTimeout。

    立即使用setTimeout 将只是push the evaluation to the back of the queue,这意味着它会等待URL 更新在读取它之前。没有这个,方法总是会落后一步。

    这是一个例子:

    <template>
        <nav>
            <ul>
                <li v-for="(item, $index) in items" :key="$index">
                    <a
                        @click="setUrlSection(item.section)"
                        :href="item.link"
                        :class="{ active: urlSection === item.link }"
                        >{{ item.name }}</a
                    >
                </li>
            </ul>
        </nav>
    </template>
    
    <script>
    export default {
        name: 'Navbar',
    
        data() {
            return {
                items: [
                    {
                        name: 'Home',
                        link: '#home',
                        section: 'hash',
                    },
                    {
                        name: 'About',
                        link: '/about',
                        section: 'pathname',
                    },
                    {
                        name: 'Contacts',
                        link: '#contact',
                        section: 'hash',
                    },
                ],
                urlSection: window.location.hash || window.location.pathname,
            };
        },
    
        methods: {
            setUrlSection(section) {
                setTimeout(() => (this.urlSection = window.location[section]));
            },
        },
    };
    </script>
    
    <style>
    ul li .active {
        background-color: red;
        cursor: pointer;
        font-weight: bold;
    }
    </style>
    

    请记住,您必须为每个项目添加一个 section 属性,以便它知道要读取哪个 window.location 属性。

    【讨论】:

    • 只是一个简单的问题,它也适用于/home, /about 类型的链接吗?还是只是#
    • 如果我想要两个/ and # 怎么办。两者都有集体解决方案吗?
    • 是的,它适用于#one,因为我现在没有 vue 路由器,所以我不能用“/”测试它。还有为什么你对家庭和联系人使用相同的部分名称但不同的关于。没关系吧?我可以将它设置为任何东西?
    • 我用 vue-router 对其进行了测试,所以它应该可以正常工作。部分属性只是为了演示如何将它与哈希和路径混合使用,因此,您可以将它与任何东西一起使用。
    • 唯一的缺陷是,如果您在链接中混合了哈希和路径,则哈希将在路径之前的页面加载时进行评估。这实际上取决于您的用例如何处理。
    【解决方案2】:

    您可以使用 VueJs :class

    <template>
      <nav>
        <ul>
          <li v-for="(item, $index) in items" :key="$index" >
            <a :href="item.link" :class="{'active': current_page_name == item.name }">{{ item.name }}</a>
          </li>
        </ul>
      </nav>
    </template>
    
    
    <script>
    export default {
      computed: {
        current_page_name() {
            return this.$route.name;
        }
      }
    }
    </script>
    

    如果您不想使用vue-router,您将不得不编写更多代码。 这是示例

    
    <script>
    export default {
      data(){
        return {
          url: '',
        }
      },
      computed: {
        current_page_name() {
    
          if(this.url){
            var URL = this.url;
            var arr=URL.split('/');
            var route_name = arr[1]; // i think zero is the domain, then 1 is the page name,
            return route_name;
          }
    
          return '';
        }
      },
    
      mounted(){
        this.url = window.location.href;
      }
    }
    </script>
    

    【讨论】:

    • 上面写着Cannot read property 'name' of undefined。来自 :class 中的 item.name
    • 确保有一个名为 items 的 prop 或变量。
    • 它肯定在那里。我检查了
    • 这是完整的错误TypeError: Cannot read property 'name' of undefined at VueComponent.current_page_name
    • 对不起,我没有测试过代码。我只是从我的脑海中写出来的。无论如何,将this.$route.name 更改为this.$router.currentRoute
    猜你喜欢
    • 1970-01-01
    • 2020-07-17
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多