近期一些web前端知识点汇聚总结(es6,算法,redux,webpack,router等)

一、js基础&es6

1.数组去重

方法一:使用Array的filter + indexOf

var arr = [1, '1', 2, 2, 3,3]

var distinctArr = arr.filter(function(element, index, self){
    
    return self.indexOf(element) === index; // 只返回首次出现的 self为数组arr
})
console.log(distinctArr);

方法二:es6的Set

var arr = [1, '1', 2, 2, 3, 3, 3, 3, 1, '1']
const items = new Set(arr); //初始化一个Set
const array = Array.from(items); // 通过Array将Set转为数组
console.log(array)

方法三:循环数组判断,符合的加入新数组

var data = [1, '1', 2, 2, 3, 3, 3, 3, 1, '1'];
Array.prototype.unique=function(){
  var arr=[];//创建新数组
  for(var i=0;i<this.length;i++){ //遍历当前数组
     if(arr.indexOf(this[i]) === -1) {
       arr.push(this[i]);
     }
  }
  
  return arr;
}

console.log(data.unique());

2.js原生深度克隆

1.浅克隆

let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);

obj1.b.c = 55; // 两个对象都修改了
console.log(JSON.stringify(obj1));//"{\"a\":0,\"b\":{\"c\":55}}"
console.log(JSON.stringify(obj2));//"{\"a\":0,\"b\":{\"c\":55}}"

2.深度克隆

方法一:通过JSON的序列化与反序列化

//对象
var obj1 = { a: 0 , b: { c: 0}, arr:[1,2,3]};
var obj2 = JSON.parse(JSON.stringify(obj1));
// 修改obj1的值
obj1.a = 4;
obj1.arr.push(4)
obj1.b.c = 4;

console.log(JSON.stringify(obj1)); // "{\"a\":4,\"b\":{\"c\":4},\"arr\":[1,2,3,4]}"
console.log(JSON.stringify(obj2)); // "{\"a\":0,\"b\":{\"c\":0},\"arr\":[1,2,3]}"

//数组
var arr1 = [1,2,3];
var arr2 = JSON.parse(JSON.stringify(arr1));
arr1.push(4);
console.log(arr1)
console.log(arr2)

方式二:原生JS

var obj1 = { a: 0 , b: { c: 0}, arr:[1,2,3]}; 

var obj2 = cloneObj(obj1);

obj1.arr.push(4);
obj1.b.c = 99;
console.log(obj1);
console.log(obj2);

function cloneObj(obj) {  
    var newObj = {};  
    if (obj instanceof Array) {  
        newObj = [];  
    }  
    for (var key in obj) {  
        var val = obj[key];  
        newObj[key] = typeof val === 'object' ? cloneObj(val): val;  
    }  
    return newObj;  
}

方式三:空数组concat

var a=[1,2,3];  
var b=a;  
var c=[].concat(a);  
a.push(4);  
console.log(b);  
console.log(c);  

二、webpack

1.loader和plugin的区别

对于loader,它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程;用于加载某些资源文件。 因为webpack 本身只能打包commonjs规范的js文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。

plugin 用于扩展webpack的功能。它直接作用于 webpack,扩展了它的功能。当然loader也时变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。

它就是一个扩展器,它丰富了wepack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,例如

  • run:开始编译
  • make:从entry开始递归分析依赖并对依赖进行build
  • build-moodule:使用loader加载文件并build模块
  • normal-module-loader:对loader加载的文件用acorn编译,生成抽象语法树AST
  • program:开始对AST进行遍历,当遇到require时触发call require事件
  • seal:所有依赖build完成,开始对chunk进行优化(抽取公共模块、加hash等)
  • optimize-chunk-assets:压缩代码
  • emit:把各个chunk输出到结果文件

通过对节点的监听,从而找到合适的节点对文件做适当的处理。

三、Router

1.React-router 中的BrowserRouter 和 HashRouter

假如有一个 Link 标签,点击后跳转到 /abc/def

  1. BrowserRouter: http://localhost:8080/abc/def
  2. HashRouter: http://localhost:8080/#/abc/def


如果有服务器端的动态支持,建议使用 BrowserRouter,否则建议使用 HashRouter

官方推荐使用browserHistory

这样看起来当然是browerHistory更好一些,但是它需要server端支持。

使用hashHistory时,因为有 # 的存在,浏览器不会发送request,react-router 自己根据 url 去 render 相应的模块。

使用browserHistory时,从 / 到 /user/liuna, 浏览器会向server发送request,所以server要做特殊请求,比如用的 express 的话,你需要 handle 所有的路由 app.get('*', (req, res) => { ... }),使用了 nginx 的话,nginx也要做相应的配置。

如果只是静态页面,就不需要用browserHistory,直接hashHistory就好了。

四、Redux + React Redux常用函数

1.redux

1. combineReducers(reducers)

combineReducers辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。

2.bindActionCreators(actionCreators,dispatch)

经过bindActionCreators处理的actions,直接调用函数就相当于进行了dispatch,因而实现了不调用dispatch即可触发state的改变。
使用场景: 当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把 Redux store 或 dispatch传给它。

3.createStore(reducer, [initState, enhancer])

  • 作用:创建一个Redux store来存放应用中所有的state,一个应用只能有个store。函数返回store对象。
  • 参数:
    • reducer(Function):两个参数:state和action,返回一个state。 不要对参数state进行修改,需要返回一个新的对象。
    • initStatate:初始state。如果不为空,需要和reducer中处理的state结构一致
    • enhancer:一个中间件,如logger等。

4.applyMiddleware(...middlewares)

输入一个middlewares数组,返回一个函数,函数以createStore为参数.

每个 middleware 接受 StoredispatchgetState函数作为命名参数,并返回一个函数。该函数会被传入 被称为 next 的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用next(action),或者在其他需要的时刻调用,甚至根本不去调用它。调用链中最后一个 middleware 会接受真实的 store 的 dispatch
方法作为 next 参数,并借此结束调用链。所以,middleware 的函数签名是 ({ getState, dispatch }) => next => action。


2.react - redux

1.connect方法

来看下connect函数到底是如何将store和组件联系在一起的,注意到api文档中有这样的一句话:

It does not modify the component class passed to it; instead, it returns a new, connected component class for you to use.

connenct并不会改变它“连接”的组件,而是提供一个经过包裹的connect组件。 conenct接受4个参数,分别是mapStateToProps,mapDispatchToProps,mergeProps,options(使用时注意参数位置顺序)。

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

mapStateToProps(state, ownProps) 方法允许我们将store中的数据作为props绑定到组件中,只要store更新了就会调用mapStateToProps方法,mapStateToProps返回的结果必须是object对象,该对象中的值将会更新到组件中,例子:

const mapStateToProps = (state) => {
    return ({
        count: state.counter.count
    })
}

mapDispatchToProps(dispatch, [ownProps]) 第二个参数允许我们将action作为props绑定到组件中,mapDispatchToProps希望你返回包含对应action的object对象,例如:

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    increase: (...args) => dispatch(actions.increase(...args)),
    decrease: (...args) => dispatch(actions.decrease(...args))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(yourComponent)

当你想对组件的render更新进行更好的控制的时候,它也支持返回function方法,具体可以点击#279查看,例子:

const mapDispatchToProps = {
    // increment: () => increment(1),
    increase, // import increase function from action
    decrease 
}

mergeProps(stateProps, dispatchProps, ownProps) 该参数非必须,redux默认会帮你把更新维护一个新的props对象,类似调用Object.assign({}, ownProps, stateProps, dispatchProps)。

而options是为了更好的定制化设置的一个参数,允许返回5个boolean、function的值,我平时基本上没有接触到,想了解的可以参考api文档。

2.Provider 组件

Context解决了一个React中很常见的问题:当你的组件嵌套越来越深的时候,context能让你父组件和其它里层组件之间的通信变的更方便,createProvider方法将返回一个Provider组件,该组件接受store和子组件,在Provider中定义了getChildContext方法来传递store,那么在子组件中利用contextTypes,你就能利用context访问到父级组件传递的store数据了。

猜你喜欢

转载自blog.csdn.net/ky1in93/article/details/81297323