首页 > 解决方案 > 为按钮组创建 vue.js 组件

问题描述

我想创建一个包含多个按钮组的网页。现有代码是

$(document).ready(function() {
  $(".nav-link").click(function() {
      console.log(this);
  });
});

Vue.component('nav-bar', {
    props: ['navs'],
    template: `<ul class="nav">
        <li v-for="nav in [{id: 0, text: 'Vege'}, {id:1, text: 'Ch'}]"
            v-bind:item="nav"
            v-bind:key="nav.id">
                <a class="nav-link" v-on:click="setactive($event)">{{ nav.text }}</a></li>
    </ul>`,
    methods: {
        setactive: function(event) {
            $(event.target).closest('ul').find('a.active').removeClass('active');
            $(event.target).addClass('active');
        },
    created: function() {
        $(this).find('a').first().addClass('active');
    }
    }
});

var app = new Vue({
    el: '#app',
    data: {
        navs: [
            { id: 0, text: 'Vegetables' },
            { id: 1, text: 'Cheese' },
            { id: 2, text: 'Milk' }
        ]
    }
});
.nav {
    display: flex;
    flex-wrap: wrap;
    list-style: none;
}
.nav-link.active {
    color: #fff;
    background-color: #007bff;
}
.nav-link {
    color: #4183c4;
    text-decoration: none;
    background-color: transparent;
    border-radius: .25rem;
    padding: .5rem 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="app">
    <nav-bar></nav-bar>
</div>

我的问题是:

我不想使用bootstrap按钮组。

标签: javascripthtmlvue.js

解决方案


if changing <li v-for="nav in [{id: 0, text: 'Vege'}, {id:1, text: 'Ch'}]" to <li v-for="nav in navs", nothing is displayed at all. Whats wrong with that?

That depends on the value of navs. We'd need to see the exact code to troubleshoot.

how can the nav items be given directly to <nav-bar>?

To pass the value of navs from App to <nav-bar>, use v-bind:

<div id="app">
  <nav-bar v-bind:navs="navs" />

  <!-- OR shorthand for v-bind -->
  <nav-bar :navs="navs" />
</div>

why isn't the first item's class set to active upon creation?

The DOM hasn't yet been stamped in the created lifecycle hook, so jQuery isn't able to find the element to set active. Since the elements you're querying are dynamically added (via the navs prop), you'd have to:

  1. Wait until the navs prop changes (instead of using a lifecycle hook). Use a watcher for this:

    Vue.component('nav-bar', {
      watch: {
        navs: {
          handler() { /* SEE NEXT STEP */ },
          immediate: true, // call handler immediately in case `navs` data is already available
        }
      }
    })
    
  2. Wait until the elements are added to the DOM in $nextTick.

    // in watch:
    handler() {
      this.$nextTick(() => {
        $(this).find('a').first().addClass('active');
      });
    },
    

Vue.component('nav-bar', {
  props: ['navs'],
  template: `<ul class="nav" ref="list">
        <li v-for="nav in navs"
            v-bind:item="nav"
            v-bind:key="nav.id">
          <a class="nav-link" v-on:click="setactive($event)">{{ nav.text }}</a>
        </li>
      </ul>`,
  methods: {
    setactive: function(event) {
      $(event.target).closest('ul').find('a.active').removeClass('active');
      $(event.target).addClass('active');
    },
  },
  watch: {
    navs: {
      immediate: true,
      handler() {
        this.$nextTick(() => {
          $(this.$refs.list).find('a').first().addClass('active');
        });
      }
    }
  }
});

var app = new Vue({
  el: '#app',
  data: {
    navs: [{
        id: 0,
        text: 'Vegetables'
      },
      {
        id: 1,
        text: 'Cheese'
      },
      {
        id: 2,
        text: 'Milk'
      }
    ]
  }
});
.nav {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
}

.nav-link.active {
  color: #fff;
  background-color: #007bff;
}

.nav-link {
  color: #4183c4;
  text-decoration: none;
  background-color: transparent;
  border-radius: .25rem;
  padding: .5rem 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="app">
  <nav-bar :navs="navs"></nav-bar>
</div>


推荐阅读