将近一年没有需要记录更新追番表的季度了

日曜日

  • anima yell!!(b 站)
  • 大人的防具店

    月曜日

  • 关于我转生成为史莱姆这档事(b 站)

    火曜日

  • 喂,看见耳朵啦
  • 天空与海洋之间(a 站)
  • 为我而生(b 站)
  • 我喜欢的是小说里的你

    水曜日

  • 青春野兔(b 站)

    木曜日

  • 佐贺偶像是传奇(a 站)
  • 邻家索菲(b 站)
  • 终将成为你(b 站)
  • 梅露可物语(b 站)

    金曜日

  • 寄宿学校的朱丽叶
  • 来自多彩世界的明天
  • 哥布林杀手
  • 彼时彼女

    土曜日

  • 月影特工(a 站)
  • himoto house

这篇文章仅仅是为了方便记忆,并不是只要知道这些就可以了

Array

_.compact(array)

创建一个新数组,包含原数组中所有的非假值元素。例如false, null, 0, “”, undefined, 和 NaN 都是被认为是“假值”
清空数组的无效值的时候会用到

_.flattenDeep(array)

将array递归为一维数组。

_.union([arrays])

创建一个按顺序排列的唯一值的数组。所有给定数组的元素值使用SameValueZero做等值比较。(愚人码头注: arrays(数组)的并集,按顺序返回,返回数组的元素是唯一的) 用于多个数组合并

  • _.uniq(array) 对一个数组去重
  • _.xor([arrays]) 取多个数组的交集

    _.zipWith([arrays], [iteratee=_.identity])

    这个方法类似于_.zip,不同之处在于它接受一个 iteratee(迭代函数),来 指定分组的值应该如何被组合。 该iteratee调用每个组的元素: (…group).

    1
    2
    3
    4
    
    _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
      return a + b + c;
    });
    // => [111, 222]
    

    Collection

    _.countBy(collection, [iteratee=_.identity])

    创建一个组成对象,key(键)是经过 iteratee(迭代函数) 执行处理collection中每个元素后返回的结果,每个key(键)对应的值是 iteratee(迭代函数)返回该key(键)的次数(愚人码头注:迭代次数)。 iteratee 调用一个参数:(value)。 ``` _.countBy([6.1, 4.2, 6.3], Math.floor); // => { ‘4’: 1, ‘6’: 2 }

// The _.property iteratee shorthand. _.countBy([‘one’, ‘two’, ‘three’], ‘length’); // => { ‘3’: 2, ‘5’: 1 }

1
2
3
4
5
6
#### [`_.every(collection, [predicate=_.identity])`](http://www.css88.com/doc/lodash/#_everycollection-predicate_identity)
通过 predicate(断言函数) 检查 collection(集合)中的 所有 元素是否都返回真值。一旦 predicate(断言函数) 返回假值,迭代就马上停止。predicate(断言函数)调用三个参数: (value, index|key, collection)。    
用于检查某个数组是否完全符合条件

#### [`_.groupBy(collection, [iteratee=_.identity])`](http://www.css88.com/doc/lodash/#_groupbycollection-iteratee_identity)
创建一个对象,key 是 iteratee 遍历 collection(集合) 中的每个元素返回的结果。 分组值的顺序是由他们出现在 collection(集合) 中的顺序确定的。每个键对应的值负责生成 key 的元素组成的数组。iteratee 调用 1 个参数: (value)。

_.groupBy([6.1, 4.2, 6.3], Math.floor); // => { ‘4’: [4.2], ‘6’: [6.1, 6.3] }

// The _.property iteratee shorthand. _.groupBy([‘one’, ‘two’, ‘three’], ‘length’); // => { ‘3’: [‘one’, ‘two’], ‘5’: [‘three’] }

1
2
#### [`_.includes(collection, value, [fromIndex=0])`](http://www.css88.com/doc/lodash/#_includescollection-value-fromindex0)
检查 value(值) 是否在 collection(集合) 中。如果 collection(集合)是一个字符串,那么检查 value(值,子字符串) 是否在字符串中, 否则使用 SameValueZero 做等值比较。 如果指定 fromIndex 是负数,那么从 collection(集合) 的结尾开始检索。

_.includes([1, 2, 3], 1); // => true

_.includes([1, 2, 3], 1, 2); // => false

_.includes({ ‘user’: ‘fred’, ‘age’: 40 }, ‘fred’); // => true

_.includes(‘pebbles’, ‘eb’); // => true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#### [`_.partition(collection, [predicate=_.identity])`](http://www.css88.com/doc/lodash/#_partitioncollection-predicate_identity)
创建一个分成两组的元素数组,第一组包含predicate(断言函数)返回为 truthy(真值)的元素,第二组包含predicate(断言函数)返回为 falsey(假值)的元素。predicate 调用1个参数:(value)。   
用于把数组一分为二
## function
#### [`_.curry(func, [arity=func.length])`](http://www.css88.com/doc/lodash/#_curryfunc-arityfunclength)
创建一个函数,该函数接收 func 的参数,要么调用func返回的结果,如果 func 所需参数已经提供,则直接返回 func 所执行的结果。或返回一个函数,接受余下的func 参数的函数,可以使用 func.length 强制需要累积的参数个数。    
**函数式编程,懂!**
#### [`_.debounce(func, [wait=0], [options={}])`](http://www.css88.com/doc/lodash/#_debouncefunc-wait0-options)
  创建一个 debounced(防抖动)函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 func 方法。 debounced(防抖动)函数提供一个 cancel 方法取消延迟的函数调用以及 flush 方法立即调用。 可以提供一个 options(选项) 对象决定如何调用 func 方法,options.leading 与|或 options.trailing 决定延迟前后如何触发(愚人码头注:是 先调用后等待 还是 先等待后调用)。 func 调用时会传入最后一次提供给 debounced(防抖动)函数 的参数。 后续调用的 debounced(防抖动)函数返回是最后一次 func 调用的结果。

注意: 如果 leading 和 trailing 选项为 true, 则 func 允许 trailing 方式调用的条件为: 在 wait 期间多次调用防抖方法。

如果 wait 为 0 并且 leading 为 false, func调用将被推迟到下一个点,类似setTimeout为0的超时。      
**滚轮和鼠标事件触发太频繁,用这个吧!**    
#### [`_.rearg(func, indexes)`](http://www.css88.com/doc/lodash/#_reargfunc-indexes)
创建一个函数,调用func时,根据指定的 indexes 调整对应位置参数。其中第一个索引值是对应第一个参数,第二个索引值是作为第二个参数,依此类推。

var rearged = _.rearg(function(a, b, c) { return [a, b, c]; }, [2, 0, 1]);

rearged(‘b’, ‘c’, ‘a’) // => [‘a’, ‘b’, ‘c’]

1
2
3
4
5
6
7
8
9
10
11
## Lang
#### [`_.cloneDeep(value)`](http://www.css88.com/doc/lodash/#_clonedeepvalue)
它会递归拷贝 value。(愚人码头注:也叫深拷贝)。
#### [`_.isEmpty(value)`](http://www.css88.com/doc/lodash/#_isemptyvalue)
检查 value 是否为一个空对象,集合,映射或者set。 判断的依据是除非是有枚举属性的对象,length 大于 0 的 arguments object, array, string 或类jquery选择器
## Number
#### [`_.random([lower=0], [upper=1], [floating])`](http://www.css88.com/doc/lodash/#_randomlower0-upper1-floating)
产生一个包括 lower 与 upper 之间的数。 如果只提供一个参数返回一个0到提供数之间的数。 如果 floating 设为 true,或者 lower 或 upper 是浮点数,结果返回浮点数。
## Object
#### [`_.at(object, [paths])`](http://www.css88.com/doc/lodash/#_atobject-paths)
http://www.css88.com/doc/lodash/#_atobject-paths

var object = { ‘a’: [{ ‘b’: { ‘c’: 3 } }, 4] };

_.at(object, [‘a[0].b.c’, ‘a[1]’]); // => [3, 4]

1
2
3
把 object 中的值转换为数组
#### [`_.functions(object)`](http://www.css88.com/doc/lodash/#_functionsobject)
创建一个函数属性名称的数组,函数属性名称来自object对象自身可枚举属性。

function Foo() { this.a = _.constant(‘a’); this.b = _.constant(‘b’); }

Foo.prototype.c = _.constant(‘c’);

_.functions(new Foo); // => [‘a’, ‘b’]

1
2
3
4
5
· [`_.functionsIn(object)`](http://www.css88.com/doc/lodash/#_functionsinobject) 获取包括原型链上的方法
#### [`_.hasIn(object, path)`](http://www.css88.com/doc/lodash/#_hasinobject-path)
检查 path 是否是object对象的直接或继承属性。
#### [`_.omit(object, [props])`](http://www.css88.com/doc/lodash/#_omitobject-props)
删除object对象的属性

var object = { ‘a’: 1, ‘b’: ‘2’, ‘c’: 3 };

_.omit(object, [‘a’, ‘c’]); // => { ‘b’: ‘2’ }

1
2
3
4
5
6
7
8
9
10
11
- [`_.pick(object, [props])`](http://www.css88.com/doc/lodash/#_pickobject-props) 提取 object 中的属性
- [`_.unset(object, path)`](http://www.css88.com/doc/lodash/#_unsetobject-path) 移除object对象 path 路径上的属性。 (**改变原对象**)   
## Util
#### [`_.attempt(func, [args])`](http://www.css88.com/doc/lodash/#_attemptfunc-args)
尝试调用func,返回结果 或者 捕捉错误对象。任何附加的参数都会在调用时传给func。
#### [`_.constant(value)`](http://www.css88.com/doc/lodash/#_constantvalue)
创建一个返回 value 的函数。
#### [`_.flow([funcs])`](http://www.css88.com/doc/lodash/#_flowfuncs)
创建一个函数。 返回的结果是调用提供函数的结果,this 会绑定到创建函数。 每一个连续调用,传入的参数都是前一个函数返回的结果。
#### [`_.iteratee([func=_.identity])`](http://www.css88.com/doc/lodash/#_iterateefunc_identity)
创建一个函数,通过创建函数的参数调用 func 函数。 如果 func 是一个属性名,传入包含这个属性名的对象,回调返回对应属性名的值。 如果 func 是一个对象,传入的元素有相同的对象属性,回调返回 true 。 其他情况返回 false 。

var users = [ { ‘user’: ‘barney’, ‘age’: 36, ‘active’: true }, { ‘user’: ‘fred’, ‘age’: 40, ‘active’: false } ];

// The _.matches iteratee shorthand. _.filter(users, _.iteratee({ ‘user’: ‘barney’, ‘active’: true })); // => [{ ‘user’: ‘barney’, ‘age’: 36, ‘active’: true }]

// The _.matchesProperty iteratee shorthand. _.filter(users, _.iteratee([‘user’, ‘fred’])); // => [{ ‘user’: ‘fred’, ‘age’: 40 }]

// The _.property iteratee shorthand. _.map(users, _.iteratee(‘user’)); // => [‘barney’, ‘fred’]

// Create custom iteratee shorthands. .iteratee = _.wrap(.iteratee, function(iteratee, func) { return !_.isRegExp(func) ? iteratee(func) : function(string) { return func.test(string); }; });

_.filter([‘abc’, ‘def’], /ef/); // => [‘def’]

1
2
3
#### [`_.overEvery([predicates=[_.identity]])`](http://www.css88.com/doc/lodash/#_overeverypredicates_identity)
建一个函数,传入提供的参数的函数并调用 predicates 判断是否 全部 都为真值。

var func = _.overEvery([Boolean, isFinite]);

func(‘1’); // => true

func(null); // => false

func(NaN); // => false

1
2
3
- [`_.overSome([predicates=[_.identity]])`](http://www.css88.com/doc/lodash/#_oversomepredicates_identity)  存在真值    
#### [`_.times(n, [iteratee=_.identity])`](http://www.css88.com/doc/lodash/#_timesn-iteratee_identity)
调用 iteratee n 次,每次调用返回的结果存入到数组中。 iteratee 调用入1个参数: (index)。

_.times(3, String); // => [‘0’, ‘1’, ‘2’]

_.times(4, _.constant(0)); // => [0, 0, 0, 0] ```

react 本身更新数组和对象,类似于 array.push() 时,是否重新渲染组件呢?
react + redux 呢?
react + redux + reselect 呢?

react

更新 state

因 react component 更新状态的方式为 this.setState(), 所以每次都会重新渲染,不过不改变引用的情况下,新老状态值会保持一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  class Parent extends Component {
    constructor() {
      super();
      this.state = {
        toDoListObj: {
          toDoList: []
        }
      }
    }
    shouldComponentUpdate(nextProps, nextState) {
      console.log(this.state.toDoListObj === nextState.toDoListObj);
    }
    componentWillUpdate() {
      console.log('parent component will update');
    }
    addToDoList() {
      const { toDoListObj } = this.state;
      toDoListObj.toDoList.push('1');
      console.log('addToDoList', toDoListObj);
      this.setState({
        toDoListObj
      })
    }
    render() {
      console.log('parent component render');
      return (
        <div >
          <h3> Parent </h3>
          <button
            onClick={this.addToDoList.bind(this)}
          >add</button>
          <div>
            {
              this.state.toDoListObj.toDoList.map(
                item => (
                  <span>item</span>
                )
              )
            }
          </div>
        </div>
      );
    }
  }

  export default Parent;

react-update-state

prop 更新

当 children component 为 PureComponent 时,父组件状态修改但不更改引用,父组件重新渲染,子组件会执行 componentWillReceiveProps 但不会重新渲染,但是这个时候 setState({state: newState}) 会重新渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  import React, { PureComponent } from 'react';

  class Children extends PureComponent {
    constructor(props) {
      super(props);
      this.state = {
        toDoList: this.props.toDoList
      }
    }
    componentWillReceiveProps(nextProps) {
      console.log('children component will receive props',
      this.props.toDoList === nextProps.toDoList);
      this.setState({
        toDoList: nextProps.toDoList
      })
    }
    render() {
      console.log('children component render', this.props);
      return (
        <div >
          <h3> Children </h3>
          <div>
            {
              this.state.toDoList.map(
                (item, index) => (
                  <span key={index}>{ item }</span>
                )
              )
            }
          </div>
        </div>
      );
    }
  }

  export default Children;
prop-update

react + redux

redux 状态更新之后,会执行所有的 mapStateToProps,然后浅比较更新前后的 props 是否一致, 如果一致,那么就不更新组件( componentWillReceiveProps 也不会执行 )。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React, { Component } from 'react';
import { connect } from 'react-redux';

class Children extends Component {
constructor(props) {
  super(props);
  this.state = {
    toDoList: this.props.toDoList
  }
}
componentWillReceiveProps(nextProps) {
  console.log('children component will receive props',
  this.props.toDoList === nextProps.toDoList);
  this.setState({
    toDoList: nextProps.toDoList
  })
}
render() {
  console.log('children component render', this.props);
  return (
    <div >
      <h3> Children </h3>
      <div>
        {
          this.state.toDoList.map(
            (item, index) => (
              <span key={index}>{ item }</span>
            )
          )
        }
      </div>
    </div>
  );
}
}

export default connect(
state => {
  console.log('state from redux', state);
  return {
    toDoList: state.toDoList
  }
}
)(Children);

redux-update

react + redux + reselect

当 redux state 改变,会执行所有的 mapStateToProps,执行 createSelector 中的 state array,这里面的值没有改变时,直接返回上次的值,如果更新,执行 selector, 然后 redux 会再进行一次检查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export const getToDoList = createSelector(
  [state => {
    console.log('in state');
    return state.toDoList;
  }],
  toDoList => {
    console.log('in selector');
    return toDoList;
  }
)
// in Children component
export default connect(
  state => {
    console.log('state from redux', state);
    let toDoList = getToDoList(state);
    console.log('from selector', toDoList);
    return {
      toDoList
    }
  }
)(Children);
selector-update

** P.S.I 一句话总结:react 中所有的检查均为浅检查,即仅检查指针是否改变(标准的 js 检查) **

Vue 相关总结

vue 采用 observer (观察者模式) 的方式决定是否渲染组件。

  1. 遍历 data 和 vuex state 并为每个定义好的值添加 observer (即使是嵌套也添加)。
  2. 当有 observer 的值改变时,重新渲染组件。
  3. 执行到 computed 和 getters 的时候,用到哪个变量(即执行某个变量的 get() ),就往他的 observer 中注册事件,当此变量变化时,再重新执行 computed 和 getters(此过程为根据现象推测)。
  4. vue 组件默认为类似 PureComponent。

reanct-native 介绍

简介

React Native 就是用 JavaScript 代码写 android 和 ios 原生应用。即 learn once, write anywhere

技术栈

  1. js、html、css
  2. ECMAScript6
  3. React 框架
  4. redux 状态管理器
  5. react-native
  6. 对 android 和 ios 开发的简单了解

    开发环境

    参照 react-native 搭建开发环境

  7. 下载 python2、node 并安装 (不能是python3)
  8. 通过 npm 安装 yarn,之后可以用 yarn add 代替 npm install --save
  9. 安装 React Native 的命令行工具 yarn add react-native-cli
  10. 安装 android studio 并配置 (android studio 的配置必须严格按照 RN 官网来,没有让勾的不能勾,否则无法运行)
  11. 配置 android 环境变量
  12. react-native init projectname 初始化项目

    开发准备

  13. 编辑器
  14. 模拟器。可以用 android studio 自带的,也可以用 genymotion
  15. 使用 react-native run-android 或者 react-native run-ios命令,用于打包生成安装包并在模拟器上运行
    • 通过 adb devices 查看目前有几个模拟器,同时只能有一个存在
    • cannot delete path … 错误可通过 cd android && gradlew.bat clean 解决
  16. 使用 react-native log-android 打印日志,输出程序中的 console.log() ( console.log() 会严重影响性能 )
log-android效果图

log-android 效果图

  1. npm install -g react-devtools 安装调试工具,react-devtools 运行该工具,用于查看内部的 dom 结构
react-devtools

react-devtools

  1. 模拟器按 Ctrl + m 或者摇晃真机呼出开发者选项,可进行设置
react-devtools

开发者菜单

1
2
3
4
5
6
7
8
- `reload` 重新加载,相当于F5
- `debug js remotely`,相当于f12,可以断点调试
- `live reload`,相当于实时F5
- `hot reloading`,热加载,相当于局部刷新,会保留之前的状态
- `toggle inspector`,相当于 <img src="../images/toggle-inspector.png" alt="">
- `show perf monitor` 开启硬件信息,如fps等 7. 关于使用 chrom 调试程序。 在开发者选项中点击 `debug js romotely` 即可在 chrome 中开启控制台。相关使用方法可以参照[如何通过 Chrome 调试 React Native 程序](https://github.com/crazycodeboy/RNStudyNotes/blob/master/React%20Native%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7%E4%B8%8E%E5%BF%83%E5%BE%97/React%20Native%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7%E4%B8%8E%E5%BF%83%E5%BE%97.md#如何通过-chrome调试react-native程序)
- 开启控制台之后 reload 可能会导致 app 闪退,重新开启 app 即可
- 开启控制台会导致 `log-android` 查看 log 的方法失效,`console.log()` 会输出到控制台的 console 中

可以开始敲代码了~

使用 react-native-video ,安装app报错

原因

版本问题:"react-native-video": "^1.2.0", 和 "react-native": "^0.47.0",

解决办法

参照 这里

使用reducer组件不更新

原因

reducer 中 newState 不能指向 state,指向的话会认为没有变化。

解决办法

newState = {...state} ps: 在 switch case 中 default 必须返回原 state,即

1
2
3
4
switch(action.type){
...
default: return state;break;
}

react-native run-android 时报 cannot delete path … 错误

解决办法

cd android && gradlew.bat clean