貼文討論:[作業問題] JavaScript系列八:第5課



OK 花了不少時間,我終於研究完了

主要問題出在這裡

  data() {
    return {
      weightChart: null,
      // ...others
    }
  },

放在 data 這邊的,會被引進 vue 的 reactivity 機制

但是,我們並不希望 weightChart 被 vue 監聽、自動更新

我們希望透過 this.weightChart.update() 手動更新,也就是我們自己管理相關 state,然後手動去觸發更新

這種情況,把 weightChart 移到 data 外面即可,就變成普通的物件屬性,不會具有 reactivity

  weightChart: null,
  data() {
    return {
      // ...others
    }
  },

執行之後會發現,「新增」沒問題了,但是「刪除」依然有問題

繼續觀察程式碼,可能有關的是這裡

  this.weightChart = new Chart(this.$refs.weightChartDOM, {
    type: 'line',
    data: {
      labels: this.dates,
      datasets: [{
        label: '體重',
        data: this.weights,
        borderWidth: 1
      }]
    },
  });

labels 與 datasets 期待的是陣列資料

使用 console.log(this.dates) 觀察變數型別,會發現我們傳進去的是帶有 vue reactivity 功能的 data(vue 使用 proxy 實作)

Chart.js 內部可能也有在監聽 變數 變化的機制,所以衝突

來試著把這邊的 reactivity 也拿掉。方法有很多種,我這邊用最土炮的一種:轉成 JSON 字串再轉回來

  this.weightChart = new Chart(this.$refs.weightChartDOM, {
    type: 'line',
    data: {
      labels: JSON.parse(JSON.stringify(this.dates)),
      datasets: [{
        label: '體重',
        data: JSON.parse(JSON.stringify(this.weights)),
        borderWidth: 1
      }]
    },
  });

除此之外,在新增、刪除的最後

  this.weightChart.data.labels = this.dates
  this.weightChart.data.datasets[0].data = this.weights
  this.weightChart.update()

也一併改掉,讓事情單純一點:我們都按照 Chart.js 期待的資料型態去傳

  this.weightChart.data.labels = JSON.parse(JSON.stringify(this.dates))
  this.weightChart.data.datasets[0].data = JSON.parse(JSON.stringify(this.weights))
  this.weightChart.update()

大功告成!解決問題!


備註一

就跟其他眾多解法一樣:以上這做法,也只算是 workaround

因為我們沒有興趣深入研究 Chart.js 監聽 labels 跟 datasets 的變化機制

(通常只有 senior developers 會在這時候想深入進去搞懂)

既然都是 workaround,就隨便找個方法搞定就是了,解法不一定很有道理(我們根本沒有100%搞懂)

備註二

proxy 型別,一般來說,會跟普通的資料型別相容

也就是說,通常把 vue reactivity 狀態,直接傳給第三方套件,根本沒問題!

不需要這樣 JSON 轉來轉去的!這是一個剛好 vue 跟第三方套件衝突的特例!

備註三

實務上,這種高互動的 UI library,都會自己出一套框架版本的,先處理掉地雷

實務上以使用框架版本為主,所以不會太常碰到這種需要 workaround 的情況(但偶爾還是會遇到)

本課的原意是故意不用框架版本,練習看看手動整合,沒想到真的踩到地雷

(但是也好,也是一種練習)

備註四

在前端框架領域,整合框架 狀態 與 html 元件、第三方外部元件 時,有兩種哲學

第一種哲學就是通通由框架處理好,這種元件稱之為 controlled components。開發元件時比較吃力,但使用元件時比較輕鬆

第二種哲學就是,自己手動管理外部元件的狀態,這種元件稱之為 uncontrolled components。開發元件時比較輕鬆,但使用元件時比較吃力

可以 google 搜尋 controlled components vs uncontrolled components,看不懂沒關係,有更多使用套件的經驗之後,會開始看懂我在講什麼


⭐️ Shopify 網站開發服務(給品牌)
https://job.turn.tw/shopify-services

⭐️ 川川電商(阿川創立的全客製電商品牌)
https://chuanchuan.tw

⭐️ 台灣 Shopify 商家交流 LINE 群(非官方)
https://line.me/ti/g2/PZ_1LILWVWWuzZQ50HNpYA-A3k6QXWF6znqoBQ

⭐️ 台灣 Shopify 開發者 LINE 群(非官方)
https://line.me/ti/g2/YUasX5K3CJ4QdIx76zppjHlh3-q8w-xkSyK1LA