[前端暴龙机,Vue2.x 进化 Vue3 ] Day19.组件练习 ref -分页(二)

今天我们会利用上一篇的 分页组件 范例来做更改,不过差别在於,这次我们父子组件的沟通不是透过 props & $emit 而是透过另一个方式来达成相同的功能

访问子组件或是子元素 : ref

接着我们今天就会透过 ref 的方式来改写上一次的分页组件范例,达到相同的功能

在子组件上定义 ref

使用方式 : 在组件上透过给定 ref 这个 attribute ,为子组件赋予一个 ID 引用

<component ref="自定义ID"></component>

父层访问子组件或是子元素的方式

this.$refs.自定义ID.要取得的子元素内容或是方法

记得,父层访问是透过 this.$refs

看到这里是不是感觉画面好像更简洁? 我们不再需要定义一堆东西在子组件上面了~


开始改写范例

HTML 部份

<div id="app">
  <ul>
      <li v-for="item in renderData">{{ item.text }}</li>
  </ul>
  <page-component ref="pages"></page-component>
</div>

这边父组件只定义 ref,用来当做与子组件沟通的桥梁

父组件部份

var app = new Vue({
  el: '#app',
  data:{
    pageIndex: 1,
    pageCount: 3,
    itemCount: 6,
    pageSize: 2,
    datas: [
        { id: 1, text: "1111" },
        { id: 2, text: "2222" },
        { id: 3, text: "3333" },
        { id: 4, text: "4444" },
        { id: 5, text: "5555" },
        { id: 6, text: "6666" },
    ],
  },
  mounted() {
      // 透过 this.$refs 去调用子组件的 init function,并传入参数 this (Vue 实例)
      this.$refs.pages.init(this);
  },
  computed:{
    renderData(){
      if (this.pageIndex === 1) {
          return this.datas.filter(ele => ele.id <= 2);
      }
      if (this.pageIndex === 2) {
          return this.datas.filter(ele => ele.id > 2 && ele.id <= 4);
      }
      if (this.pageIndex === 3) {
          return this.datas.filter(ele => ele.id > 4 && ele.id <= 6);
      }
    }
  },
  methods:{
      updatePage(idx) {
          this.pageIndex = idx;
          
          // 透过 this.$refs 去调用子组件的 init function,确保资料有同步
          this.$refs.pages.init(this);
      }
  }
})

透过 this.$refs 去调用子组件的方法,并将 Vue 实例 当作参数传给 子组件

子组件部份 ( component )

Vue.component('page-component', {
    template: `
        <div>
            <button type="button" @click="prev">上一页</button> 
            <button type="button" :class="{pagenow: pageNow === item}" v-for="item in totalPage" @click="pageTo(item)">{{ item }}</button> 
            <button type="button" @click="next">下一页</button>
        </div>
    `,
    data: function () {
        return {
            pageNow: 1,
            totalPage: 1,
            fatherVue: null,
        }
    },
    methods: {
        init(parentVue) {
            this.fatherVue = parentVue;
            this.totalPage = parentVue.pageCount;
            this.pageNow = parentVue.pageIndex;
        },
        prev() {
            if (this.fatherVue.pageIndex <= 1) return;
            this.pageNow--;
            this.fatherVue.updatePage(this.pageNow);
        },
        next() {
            if (this.fatherVue.pageIndex === this.fatherVue.pageCount) return;
            this.pageNow++;
            this.fatherVue.updatePage(this.pageNow);
        },
        pageTo(idx) {
            this.fatherVue.updatePage(idx);
        }
    },
});

子组件在父组件呼叫 init function 时,初始化并同步数据
并将父组件传过来的参数 this >> init(parentVue) 储存为 fatherVue,用来与父组件沟通
所以用 this.fatherVue.updatePage(参数); ,请父组件更新讯息
就完成了跟上一次一样的功能了~
https://ithelp.ithome.com.tw/upload/images/20210818/20120722kcZb0ndKWF.jpg

其实父子组件的沟通,还有其他的方式,不过这边就只稍微介绍两种我自己运用的方式

  1. props & $emit
  2. ref

还有 Vuex ... 等,但就有兴趣再去找找文章啦~

范例展示


参考资料

itread01.com , Vue元件间通讯6种方式
Vue 官方文件 - 访问子组件实例或子元素
码上快乐 , Vue.js中ref ($refs)用法举例总结


<<:  Day-27 游戏主机全员到齐、一同聚集於客厅

>>:  CSS 定位属性(DAY15)

[13th-铁人赛]Day 2:Modern CSS 超详细新手攻略 - 入门

WHO? WHAT? CSS到底是谁? CSS的全名为Cascading Style Sheets,...

Day20-不能说的秘密(二)

前言 昨天有说到在储存使用者的密码时,不管是用 AES 把他们加密起来,或是经过 SHA1 杂凑之後...

[DAY 28] _看门狗简介_视窗看门狗(2)

昨天主要介绍了视窗看门狗和独立看门狗的差别,今天来看这如何计算,这计算方式再参考手册里面有举例说明,...

不用Recoil的话,如何自己制作一个 Custom hook 来共享全域变数?(2)

实作自己的全域 count, setCount codesandbox demo const { c...

[Day 31] - 手把手跨出第一步!将Arduino打造成JavaScript的环境-Part 1

大家好,我是17King~ d(`・∀・)b 好久不见,因为最近比较多事情! 但!我没有忘记要po(...