为了账号安全,请及时绑定邮箱和手机立即绑定

vuex给getter传参的官方例子解读

最近遇到一个需求,需要在使用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]: https://cnodejs.org/topic/56a1d827cd415452622eed07
  [2]: https://developer.ibm.com/node/2016/01/11/higher-order-functions-in-es6easy-as-a-b-c/
  [3]: https://cnodejs.org/topic/56a1d827cd415452622eed07
点击查看更多内容
17人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消