Создание активного класса в меню во Vue

Я пытаюсь получить доступ к элементу привязки в вычисляемом свойстве, чтобы определить, должен ли он быть активным или оставаться как есть.

Я видел примеры использования v-for и циклического перебора свойств данных, но это статическое меню, например:

<template>
<div class="panel panel-default">
    <div class="panel-heading">Application Menu</div>
    <ul class="list-group">
        <a :href="route('applications.index')" 
           :class="activeClass" 
           class="list-group-item">Applications</a>
        <a :href="route('applications.repository')" 
           :class="" 
           class="list-group-item">Token Repository</a>
        <a :href="route('applications.notifications')" 
           :class="" 
           class="list-group-item">Notifications</a>
    </ul>
</div>
</template>

Моя activeClass вычисленная опора будет сравнивать href текущей привязки с текущим местоположением браузера и возвращать active, если они совпадают.

Я изучил всю документацию на веб-сайте Vue и много погуглил, и я еще не нашел способа получить доступ к атрибуту href привязки, вызывающей вычисляемое свойство.


person Vince Kronlein    schedule 14.10.2018    source источник


Ответы (3)


Вы не можете этого сделать, и вот почему. Вычисляемое свойство должно быть универсальным. Другими словами, его значение не определяется тем, кто к нему обращается. Если вы обращаетесь к this.activeClass изнутри метода, его значение должно быть таким же, как activeClass внутри шаблона, при условии, что информация о состоянии, от которой он зависит, такая же. (И кто получает к нему доступ - не государственная информация)

Если вы используете Vue-Router, вы можете просто сравнить значение $ route.path и использовать другой класс. Например:

<a :href="route('applications.index')" 
   :class="$route.path === 'whatever' ? 'active-class' : 'inactive-class'">Applications</a>
person Ken Kinder    schedule 14.10.2018

Вы неправильно думаете об этом. Вы не должны пытаться получить доступ к атрибутам элементов DOM, как если бы они были данными. DOM - это не хранилище данных. Данные должны быть в вашей модели просмотра и использоваться в DOM.

У вас должен быть массив объектов, описывающих ваши предметы. (Кроме того, единственными разрешенными дочерними элементами ul являются li.) Вы можете сделать что-то вроде этого:

<ul class="list-group">
    <li v-for="item in menuItems">
      <a :href="item.route" 
         :class="isActive(item)" 
         class="list-group-item">{{model.label}}</a>
    </li>
</ul>

Если вы хотите иметь computed, который работает для каждого из ваших элементов, вам нужно будет создать компонент для каждого элемента. См. vuejs с использованием вычисляемого свойства для элементов массива

person Roy J    schedule 14.10.2018
comment
Я мог бы легко переключить это на разработчика, либо отобразить то же самое в хроме. Кроме того, для этого нет модели, это базовый партиал Laravel, который отображает компонент vue. Спасибо хоть. - person Vince Kronlein; 14.10.2018

Окончательное решение:

<template>
<div class="panel panel-default">
    <div class="panel-heading">Application Menu</div>
    <ul class="list-group">
        <a :href="route('applications.index')" 
           :class="activeClass('applications')" 
           class="list-group-item">Applications</a>
        <a :href="route('applications.repository')" 
           :class="activeClass('repository')" 
           class="list-group-item">Token Repository</a>
        <a :href="route('applications.notifications')" 
           :class="activeClass('notifications')" 
           class="list-group-item">Notifications</a>
    </ul>
</div>
</template>

<script>

export default {
    data () {
        return {
            currentLink: location.href,
        }
    },
    computed: {
        routes() {
            return window.routes
        },
    },
    mounted() {
        this.setCurrentLink()
    },
    methods: {
        route(url) {
            return this.routes.route(url)
        },
        activeClass(segment) {
            return segment == this.currentLink ? 'active' : ''
        },
        setCurrentLink() {
            this.currentLink = new URL(location.href).pathname.split('/').pop();
        }
    }
}
</script>

Отлично работает без необходимости повторять цикл. Я называю это редким вариантом использования, но для чего-то маленького и статичного он отвечает всем требованиям.

Спасибо всем, кто внес свой вклад.

person Vince Kronlein    schedule 14.10.2018