首页 > 解决方案 > Vue.js - 全局共享状态和组件外的 for 循环 - 这是一个好习惯吗?

问题描述

我是 Vue.JS 的新手。我试图实现两个书籍列表(已阅读和未阅读),书籍列表是共享对象(在全局数据状态下)。

这是我的解决方案 -工作演示它有效!但我问自己这是否被认为是一种好的做法,我有一些问题,也许你可以帮助澄清)

的HTML:

<div id="root">
  <h2>Books pending to read</h2>
  <ul>
    <book-li 
      v-for="book of notReadedBooks"
      :key="book.id"
      :book="book.title"
      :status="book.readed"
      @changeit="changeStatus(book.id)">
    </book-li>
  </ul>

  <h2>Readed books</h2>
  <ul>
    <book-li 
      v-for="book of readedBooks"
      :key="book.id"
      :book="book.title"
      :status="book.readed"
      @changeit="changeStatus(book.id)">
    </book-li>
  </ul>
</div>

的JavaScript:

Vue.component('book-li', {
  props: [ 'book', 'status' ],
  template: `
    <li>
      {{ book }} – <button @click="$emit('changeit')"> {{status ? 'will reread' : 'readed'}} </button>
    </li>
  `
})


const App = new Vue({
  el: '#root',
  data: {
    allBooks: [
      { title: 'El Aleph', id: 101, readed: true },
      { title: 'Ficciones', id: 102, readed: false  },
      { title: 'La torre de Babel', id: 103, readed: false  },
    ]
  },

  computed: {
    readedBooks: function() { return this.allBooks.filter( singleBook => singleBook.readed )},
    notReadedBooks: function() { return this.allBooks.filter( singleBook => ! singleBook.readed )},
  },

  methods: {
    changeStatus(idCurrentBook) {
      let bookIndex = this.allBooks.findIndex(book => book.id === idCurrentBook)
      this.allBooks[bookIndex].readed = ! this.allBooks[bookIndex].readed
    }
  }
})

如您所见,我遍历了 2 个计算列表(已读取和未读取),但我试图以更好的方式呈现它。例如:

1 - 我无法将整个已读/未读列表传递给组件,然后定义一个v-for内部带有循环的组件。

类似于<book-list :list="readedBooks"></book-list> 然后在该组件内部v-forlist道具执行操作。这在 Vue 上是否可行,或者循环应该发生在组件之外?

2 - 我发现的另一个问题是,如果我将:book属性绑定重命名为,:book-title那么 Vue 会告诉我需要定义一个:book属性,即使我不会使用它(?)。

提前感谢您的帮助!


编辑:

感谢@luca-faggianelli 给我一些见解。

我设法在v-for内部创建了一个循环,因此可以大大简化代码:


<div id="root">
  
  <h2>Books pending to read</h2>
    <books :list="notReadedBooks"></books>

  <h2>Readed books</h2>
    <books :list="readedBooks"></books>

</div>
Vue.component('books', {
  props: [ 'list' ],
  template: `
  <ul>
    <li v-for="book in list">
      {{ book.title }} - <button @click="book.readed = !book.readed">{{ book.readed ? 'read again' : 'readed' }}</button>
    </li>
  </ul>
  `
})

const App = new Vue({
  el: '#root',
  data: {
    allBooks: [
      { title: 'El Aleph', id: 101, readed: true },
      { title: 'Ficciones', id: 102, readed: false  },
      { title: 'La torre de Babel', id: 103, readed: false  },
    ]
  },
  computed: {
    readedBooks: function() { return this.allBooks.filter( singleBook => singleBook.readed )},
    notReadedBooks: function() { return this.allBooks.filter( singleBook => ! singleBook.readed )},
  }
})

标签: javascripthtmlvue.jsvuejs2

解决方案


我建议您开始阅读有关 Vue 组件的内容https://vuejs.org/v2/guide/components.html

然后回答你的问题:

  1. 它可以创建一个<book-list>组件,并确保您可以在组件内拥有 for 循环

  2. 您必须book在组件声明中重命名属性,即在:

Vue.component('book-li', {
  props: [ 'bookTitle', 'status' ],

然后你可以使用:book-title,注意 Vue 需要 HTML 中的 kebab-case 道具和 JS 中的 camelCase


推荐阅读