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

日曜日

  • 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 componentPureComponent 时,父组件状态修改但不更改引用,父组件重新渲染,子组件会执行 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. 遍历 datavuex state 并为每个定义好的值添加 observer (即使是嵌套也添加)。
  2. 当有 observer 的值改变时,重新渲染组件。
  3. 执行到 computedgetters 的时候,用到哪个变量(即执行某个变量的 get() ),就往他的 observer 中注册事件,当此变量变化时,再重新执行 computedgetters(此过程为根据现象推测)。
  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 casedefault 必须返回原 state,即

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

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

解决办法

cd android && gradlew.bat clean