vuex給getter傳參的官方例子解讀

gamebus發表於2021-09-09

最近遇到一個需求,需要在使用vuex的getter獲取資料的時候傳入引數。遇到問題當然首先是檢視文件,然鵝,一臉懵逼。當然最後透過我不斷的努(bai)力(du) ,終於能夠理解那個官方demo了。為了自己以後複習以及服(zhi)務(shi)小(xiang)夥(zhuang)伴(bi),決定把個人理解記錄下來,如果各位看官發現有什麼問題,請及時和我聯絡,這樣我就知道又有一個 人看了我的文章!!!

官方說明(短小精悍):你也可以透過讓 getter 返回一個函式,來實現給 getter 傳參。在你對 store 裡的陣列進行查詢時非常有用。

官方demo(一臉懵逼):

getters: {
  // ...
  getTodoById: (state, getters) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

首先,我遇到的第一個問題就是那個連續不斷的箭頭函式是什麼鬼(不知道箭頭函式的麻煩出門自行百度)?當然,這個東西還是比較好辦的,箭頭函式一大堆看不懂,我們可以 還原成看的懂的啊,說幹我們就幹。

getTodoById: function(state, getters) {
  return function(id) {
    return state.todos.find(function(todo)  {
      return todo.id === id;
    })
  }
}

store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

這裡沒有涉及到this的引用,就不對this做處理了,效果是一樣的。

看到了這裡差不多就明白了。

首先:我們使用獲得了一個由store.getters.getTodoById返回的匿名函式。
然後:我們立刻傳入了引數'2'執行了這個函式。
最後:看起來就像是我們直接傳入了引數給store.getters.getTodoById函式,但是其實getter是隻能接受預設引數的:state或者一個 可選的其他getter,並不支援使用者隨意傳入引數。

到這裡基本就可以理解上面的官方demo以及正確使用了。

然後,我們們來聊一聊連續箭頭函式這個東西。

以下全部轉載自:[ES6 高階箭頭函式][1]

先來看下高階函式定義:

  • 接受1個或多個函式作為引數
  • 返回函式型別
    常規ES6箭頭函式用法:(返回值型別)
    const square = x => x * x;

    高階寫法:

    const has = p => o => o.hasOwnProperty(p);
    const sortBy = p => (a, b) => a[p] > b[p];

    理解語法

ES5實現高階函式,也叫柯里化:

function add(x){
  return function(y){
    return y + x;
  };
}

var addTwo = add(2);
addTwo(3);          // => 5
add(10)(11);        // => 21

add函式接受x,返回一個函式接受y返回y+x。如何用箭頭函式實現同樣功能呢?我們知道:

箭頭函式體是表示式,並且箭頭函式隱式返回表示式,所以為了實現高階函式,我們可以使箭頭函式的函式體為另一個箭頭函式:

const add = x => y => y + x;
// outer function: x => [inner function, uses x]
// inner function: y => y + x;

這樣我們可以建立一個繫結了x的內部函式:

const add2 = add(2);// returns [inner function] where x = 2
add2(4);            // returns 6: exec inner with y = 4, x = 2
add(8)(7);          // 15

這個例子看起來沒什麼實際作用,但是很好的展示瞭如何在返回的函式中引用外部引數。

使用者排序例子

const has = p => o => o.hasOwnProperty(p);
const sortBy = p => (a, b) => a[p] > b[p];

let result;
let users = [
  { name: 'Qian', age: 27, pets : ['Bao'], title : 'Consultant' },
  { name: 'Zeynep', age: 19, pets : ['Civelek', 'Muazzam'] },
  { name: 'Yael', age: 52, title : 'VP of Engineering'}
];

result = users
  .filter(has('pets'))
  .sort(sortBy('age'));

上述程式碼利用了Arraysortfilter 方法,這兩個方法都接收一個函式引數,此處我們利用了箭頭函式的高階函式寫法返回需要的函式。

對比下直接傳入函式的寫法:

result = users
  .filter(x => x.hasOwnProperty('pets')) //pass Function to filter
  .sort((a, b) => a.age > b.age);        //pass Function to sort

高階函式寫法:

result = users
  .filter(has('pets'))  //pass Function to filter
  .sort(sortBy('age')); //pass Function to sort

優勢在哪?

  • 減少程式碼重複
  • 提高程式碼重用性
  • 更容易閱讀的程式碼
    假設我們想列出有pets和title的使用者,可以採用如下傳統寫法:
    result = users
    .filter(x => x.hasOwnProperty('pets'))
    .filter(x => x.hasOwnProperty('title'))

    採用高階函式寫法:

    result = users
    .filter(has('pets'))
    .filter(has('title'))
    ...

    可以明顯感受到高階寫法更容易寫和維護。

更進一步

假設想實現一個過濾器函式完成如下功能:判斷一個物件是否包含指定值的key。之前的has函式用於檢查物件key,我們需要在此基礎上加入值的檢查:

//[p]roperty, [v]alue, [o]bject:
const is = p => v => o => o.hasOwnProperty(p) && o[p] == v;

// broken down:
// outer:  p => [inner1 function, uses p]
// inner1: v => [inner2 function, uses p and v]
// inner2: o => o.hasOwnProperty(p) && o[p] = v;

所以我們的新函式is做了下面三件事:

  1. 接收屬性名返回函式…
  2. 接收值返回函式…
  3. 接收物件,並判讀該物件是否有指定的屬性名和值,並返回boolean
    下面是一個使用is函式的例子:
    
    const titleIs = is('title');
    // titleIs == v => o => o.hasOwnProperty('title') && o['title'] == v;

const isContractor = titleIs('Contractor');
// isContractor == o => o.hasOwnProperty('contractor') && o['title'] == 'Contractor';

let contractors = users.filter(isContractor);
let developers = users.filter(titleIs('Developer'));

let user = {name: 'Viola', age: 50, title: 'Actress', pets: ['Zak']};
isEmployed(user); // true
isContractor(user); // false

關於命名習慣

下面的寫法需要你花點時間去理解其含義:

const i = x => y => z => h(x)(y) && y[x] == z;

使用一些更明確含義的引數命名:

const is = prop => val => obj => has(prop)(obj) && obj[prop] == val;

###繼續

如果我們想進一步提供排序功能,但是僅改為降序排列,或者列出不包含某屬性的使用者,我們需要重新實現諸如 `sortByDesc` 和 `notHas`這樣的新函式嗎?答案是不需要,對於最終返回結果是boolean值的高階函式,我們可以對其進行取反包裝,如下:

//take args, pass them thru to function x, invert the result of x
const invert = x => (...args) => !x(...args);
const noPets = invert(hasPets);

let petlessUsersOldestFirst = users
.filter(noPets)
.sort(invert(sortBy('age')));


## 結論
>函數語言程式設計受到越來越多的重視,ES6的箭頭函式提供了更簡潔方便的JavaScript實現方式,如果你還沒有看到這種方法的廣泛使用,那麼可以預見在未來幾個月函數語言程式設計會伴隨ES6的普及變得更為流行。即使你不太喜歡這種方式,那麼理解高階函式也是非常有必要的。

原始資料:[Higher order functions in ES6:Easy as a => b => c;][2]  

中文摘譯版:[ES6 高階箭頭函式][3]

  [1]: 
  [2]: https://developer.ibm.com/node/2016/01/11/higher-order-functions-in-es6easy-as-a-b-c/
  [3]: 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4687/viewspace-2799639/,如需轉載,請註明出處,否則將追究法律責任。

相關文章