Skip to content

Vue.js 父子组件交互:props、自定义 v-model #136

Description

@JasonWu73

本文项目沿用 Vue.js 单文件组件入门(非 Node.js 环境)

分页组件(子组件)PageBar.vue

<template>
  <!-- 因为 Vue 要求每个组件只能有一个 root 元素,故这里需要使用 `div` 将 `a` 标签包裹起来 -->
  <div>
    <a href="javascript:void(0);"
       v-for="num in totalPage"
       :class="{active: currentPage === num}"
       @click="changePage(num)"
    >第{{num}}页</a>
  </div>
</template>

<script>
  module.exports = {
    data() {
      return {
      };
    },
    // 重新映射 `v-model` 的属性值
    model: {
      prop: 'currentPage', // 默认为 `value`,
      event: 'changeCurrentPage', // 默认为 `input`
    },
    // `props` 属性:用于向子组件传递数据
    // 注意命名自动转换规则
    props: ['totals', 'pageSize', 'currentPage'],
    computed: {
      totalPage() {
        // 每页 `pageSize` 条,有小数,则+1
        // 若列表长度为0,则显示1
        return Math.ceil(this.totals / this.pageSize) || 1;
      }
    },
    methods: {
      changePage(num) {
        // 触发 `v-model` 事件
        this.$emit('changeCurrentPage', num);
      }
    }
  };
</script>

<style scoped></style>

书单列表组件(父组件)BookList.vue

<template>
  <dl>
    <dt>图书列表(单文件组件)</dt>
    <dd class="page">
      <!-- Vue.js 为 components 和 props 提供了自动命名大小写转换规则,
      但并没有为自定义事件提供此类自动命名转换规则,
      详见:https://vuejs.org/v2/guide/components-custom-events.html#Event-Names -->
      <page-bar
          :totals="bookTotal"
          :page-size="pageSize"
          v-model="currentPage"></page-bar>
    </dd>
    <dd>
      <input type="text" v-model="currentPage">
      <!-- 等同于 -->
      <input type="text" :value="currentPage" @input="currentPage = $event.target.value">
    </dd>
    <dd v-for="book in bookList">
      {{book.row_index}}. 《{{book.book_name}}》 - CN¥{{book.book_price}} - {{book.book_press}}
    </dd>
  </dl>
</template>

<script>
  const PageBar = httpVueLoader('../common/PageBar.vue');

  // 注意:这里必须是以 CommonJS(Node.js) 的 `module.exports` 方式导出,而不能是 ES6 的 `export default`
  // 建议阅读:https://stackoverflow.com/questions/40294870/module-exports-vs-export-default-in-node-js-and-es6
  module.exports = {
    // 组件中的 `data` 必须为函数
    data() {
      return {
        bookList: [],
        bookTotal: 0,
        pageSize: 10,
        currentPage: 1
      };
    },
    created() {
      this.getBookList();
    },
    beforeUpdate() {
      this.getBookList();
    },
    methods: {
      getBookList() {
        axios.get(`/books?page=${this.currentPage}&page_size=${this.pageSize}`)
        .then(response => {
          const {book_list: bookList, total} = response.data.result;
          this.bookList = bookList;
          this.bookTotal = total;
        });
      }
    },
    components: {
      'page-bar': PageBar
    }
  }
</script>

<style scoped>

</style>

Metadata

Metadata

Assignees

No one assigned

    Labels

    参考示例程序

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions