1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
例子: let cols = document.querySelectorAll('ul li') [].forEach.call(cols, function (col, index) { // TODO } 分析: ① []是一个空数组,无论这个数组里的最初值是什么,它们都不会被使用到; ② forEach方法是一个数组方法,只有数组才能调用;完整写法:Array.prototype.forEach,Array.forEach为简写; ③ call方法: 语法:fun.call(thisArg, arg1, arg2, ...) 参数:thisArg:在 fun 函数运行时指定的this值; arg1, arg2, ... : 指定的参数列表; 综上:[]这个空数组里的值(当然,它没有值)是最初的this值,通过call方法,当这个空数组调用方法forEach时, cols里的值会取代空数组原先的this值。 通俗的说,就是cols需要使用forEach这个方法, 但是这个方法是一个数组方法,只有数组才能调用,于是通过call方法来了个偷梁换柱, 在数组调用forEach方法的时候,将数组里的this值替换成了cols的值,达成了目的。 |
分类:前端
解决React首屏加载白屏的问题
Cannot resolve symbol ‘Component’ & Cannot resolve symbol ‘PropTypes’
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import React, { Component, PropTypes } from 'react' 报错:Cannot resolve symbol 'Component' Cannot resolve symbol 'PropTypes' 1.解决 Cannot resolve symbol 'Component' 安装依赖:npm install @types/react --save 调用方法:import React, { Component } from 'react' 2.解决 Cannot resolve symbol 'PropTypes' 安装依赖:npm install prop-types --save 调用方法:import PropTypes from 'prop-types' 注:React.PropTypes 自 React v15.5 起已弃用。请使用 prop-types 库代替。 |
React & Redux 的一些基本知识点
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
一、React.createClass 跟 React.Component 的区别在于后者使用了ES6的语法,用constructor构造器来构造默认的属性和状态。 1. React.createClass import React from 'react'; const Contacts = React.createClass({ render() { return ( <div></div> ); } }); export default Contacts; 2.React.Component import React from 'react'; class Contacts extends React.Component { constructor(props) { super(props); } render() { return ( <div></div> ); } } export default Contacts; 二、 Super(props) 调用父类的构造函数,react希望把所有props,state的定义尽量放到父类中进行。 子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象, 而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。 三、容器组件 Container Components 和展示组件 Presentational Components -------------------------------------------------------------------------- | 展示组件 | 容器组件 -------------------------------------------------------------------------- 作用 | 描述如何展现(骨架、样式) | 描述如何运行(数据获取、状态更新) -------------------------------------------------------------------------- 直接使用Redux | 否 | 是 -------------------------------------------------------------------------- 数据来源 | props | 监听 Redux state -------------------------------------------------------------------------- 数据修改 | 从 props 调用回调函数 | 向 Redux 派发 actions -------------------------------------------------------------------------- 调用方式 | 手动 | 通常由 React Redux 生成 -------------------------------------------------------------------------- <strong>四、connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])</strong> 连接 React 组件与 Redux store。连接操作不会改变原来的组件类,而是返回一个新的已与 Redux store 连接到组件类。 1.[mapStateToProps(state, [ownProps]): stateProps] (Function): 如果定义该参数,组件将会监听 Redux store 的变化。只要 Redux store 发生变化,mapStateToProps函数就会被调用。 该回掉函数必须返回一个纯对象,这个对象与组件的props合并。如果省略了这个参数,组件将不会监听 Redux store。 如果指定了第二个参数 ownProps,则该参数的值为传递到之间的props,而且只要组件接收到新的 props, mapStateToProps也会被调用。 2.[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function): 如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator, 对象所定义的方法名将作为属性名;每个方法将返回一个新的函数,函数中dispatch方法会将action creator的返回值作为参数执行。 这些属性会被合并到组件的 props 中。如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象, 这个对象通过 dispatch 函数与 action creator 以某种方式绑定在一起(提示:你也许会用到 Redux 的辅助函数 bindActionCreators())。 如果你省略这个 mapDispatchToProps 参数,默认情况下,dispatch 会注入到你的组件 props 中。 如果指定了该回调函数中第二个参数 ownProp该参数的值为传递到组件的 props,而且只要组件接收到新 props,mapDispatchToProps 也会被调用。 3.[mergeProps(stateProps, dispatchProps, ownProps): props] (Function): 如果指定了这个参数,mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。 该回调函数返回的对象将作为 props 传递到被包装的组件中。你也许可以用这个回调函数,根据组件的 props 来筛选部分的 state 数据, 或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。 4.[options] (Object): 如果指定这个参数,可以定制 connector 的行为。 [pure = true] (Boolean): 如果为 true,connector 将执行 shouldComponentUpdate 并且浅对比 mergeProps 的结果, 避免不必要的更新,前提是当前组件是一个“纯”组件,它不依赖于任何的输入或 state 而只依赖于 props 和 Redux store 的 state。默认值为 true。[withRef = false] (Boolean): 如果为 true,connector 会保存一个对被包装组件实例的引用, 该引用通过 getWrappedInstance() 方法获得。默认值为 false。 |
react-router 3 中的 useRouterHistory(createHistory) 到了 react-router 4 变成了什么?
react-router 3 文档: https://github.com/ReactTraining/react-router/blob/v3/docs/API.md
react-router 4 文档: https://reacttraining.com/react-router[……]
react-router 4 文档: https://reacttraining.com/react-router[……]
一个 React & Redux的目录树
React & Redux
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
Project | |-- node_modules | | | |-- react | | | |-- react-dom | | | |-- react-router | | | |-- react-redux => redux本身只能处理同步的Action | | | |-- react-thunk => 在我们没有加上thunk这个中间件之前, | | store的dispatch方法只能传入一个action对象, | | thunk的作用就是能够让我们可以将一个function方法传入diptach, | | 这在做异步的时候非常有用。 | | | |-- redux-promise => redux-promise支持将promise对象作为参数传入dispatch中。 | | | |-- prop-types => React.PropTypes 自 React v15.5 起已弃用。 | | 请使用 prop-types 库代替。调用方法: | | import PropTypes from 'prop-types' | | | |-- @types/react => implements method in React.Component,解决 | | Cannot resolve symbol 'Component' 的问题 | | | |-- postcss-loader => PostCSS,一款通过 JS 插件转换 styles 样式的工具。 | | 根目录下新建postcss.config.js文件。配置如下: | | module.exports = { | | parser: 'sugarss', | | plugins: { | | 'postcss-import': {}, | | 'postcss-cssnext': {}, | | 'cssnano': {} | | } | | } | | webpack配置:{ | | test: /\.css$/, | | use: ['style-loader', 'css-loader','postcss-loader'] | | } | | | |-- Autoprefixer => PostCSS插件,一个后处理程序。解析CSS并添加浏览器前缀。 | | postcss.config.js文件中配置如下: | | module.exports = { | | plugins: [ | | require('autoprefixer')({}) | | ] | | } | | | |-- extract-text-webpack-plugin => 将css单独打包成一个文件。 | | 它会将所有的入口 chunk(entry chunks)中引用的 *.css, | | 移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到JS bundle中, | | 而是会放到一个单独的 CSS 文件(即 styles.css)当中。 | | 如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle | | 会跟 JS bundle 并行加载。 | | | |-- optimize-css-assets-webpack-plugin => 压缩抽离后的css代码, | | plugins: [new OptimizeCssAssetsPlugin()] | | | |-- html-webpack-plugin => 该插件将为您生成一个HTML5文件, | | 其中包括使用script标签的body中的所有webpack包。 | | | |-- copy-webpack-plugin => 在webpack中拷贝文件和文件夹。例如: | | new CopyWebpackPlugin([ | | {from: "./src/static/images", to: 'images/'} | | ]) | | 作用就是将 ./src/static/images | | 目录下的图片拷到编译目录到 images 文件夹下面 | | | |-- rimraf => 编译前清空dist目录。package.json配置: | | "scripts": {"build": "rimraf dist && ..."} | | | |-- OpenBrowserPlugin => webpack编译后自动打开浏览器 | | | |-- axios => 一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 | | | |-- babel-eslint => 一个Babel parser的包装器,这个包装器使得Babel parser可以和ESLint协调工作 | | .eslintrc.js中配置:"parser": "babel-eslint", | | "parserOptions": { | | "sourceType": "module", | | "allowImportExportEverywhere": false, | | "codeFrame": false | | } | | | |-- webpack | | | |-- webpack-dev-middleware | | | |-- webpack-hot-middleware | |-- dist => 打包输出文件目录 | |-- src | | | |-- actions => Action是把数据从应用传到 store 的有效载荷。 | | 它是 store 数据的唯一来源,一般通过 | | store.dispatch() 将 action 传到 store。 | | | |-- reducers => Action只是描述了有事情发生了这一事实, | | 并没有指明应用如何更新 state。 | | reducer 用来做更新state这个动作。 | | | |-- store => 1.维持应用的state; | | 2.提供 getState() 方法获取 state; | | 3.提供 dispatch(action) 方法更新state; | | 4.通过 subscribe(listener) 注册监听器; | | 5.通过 subscribe(listener) 返回的函数注销监听器。 | | | |-- components => 展示型组件目录 | | | |-- containers => 容器型组件目录 | | | |-- config => 配置actionType、接口 | | | |-- library => 插件库 | | | |-- service => 服务配置 | | | |-- static => 静态文件目录 | | | |-- main.js => 入口文件 | |-- webpack => webpack配置目录 | |-- .babelrc => Bable的配置文件,用来设置转码规则和插件。 | Babel是一个广泛使用的ES6转码器, | 可以将ES6代码转为ES5代码。 | |-- .gitignore => git上传忽略特殊文件配置 | |-- index.html | |-- README.md | |-- package.json => 定义了这个项目所需要的各种模块,以及项目的配置信息。 | |-- package-lock.json => npm5.0后新增。记录了整个 node_modules | 文件夹的树状结构,当重新安装模块的时候, | 速度加快。但是,生成pack-lock.json后, | 重复执行npm install时将会以其记录的版本来安装。 | 这时如果手动修改 package.json 中的版本, | 重新安装也不会生效,只能手动执行npm install | 命令指定依赖版本来进行修改。 | | |-- yarn.lock => yarn.lcok文件是自动产生的, | 和package-lock.json的功能一样, | 只不过yarn可以做到手动更改package.json后, | 重新安装并更新lockfile。 |
vue中使用 echarts3.0 或 echarts2.0
一、echarts3.0(官网: http://echarts.baidu.com/)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
首先通过npm安装echarts依赖,安装的为3.0版本 npm install echarts -s 也可以使用淘宝镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org cnpm install echarts -s 引入的方式有两种: 1、main.js中全局引入 import echarts from 'echarts' Vue.prototype.$echarts = echarts 然后在组件中通过 this.$echarts.init(document.getElementById('your_div')) 来初始化 2、只应用基本包,加快加载速度 在需要使用echarts的组建中引入: let echarts = require('echarts/lib/echarts') 然后通过 echarts.init(document.getElementById('your_div')) 来初始化 使用的话就比较简单,直接将官方实例封装一个为方法,在mounted中调用即可。 |
二、 echarts2.0(官网: http://echarts.baidu.com/echarts2/)
[crayon-6740c186[……]
Javascript异步编程
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
1、什么是异步(Asynchronous)编程? 相对于同步(Synchronous)而言,异步就是后一个任务不需要等待前一个任务结束就执行,而前一个任务结束以后执行回调函数。 最常见的异步编程有setTimeout函数、 ajax请求等。 如: for (var i = 1; i <= 3; i++) { setTimeout(function(){ console.log("#",i); }, 0); console.log("*",i); }; 输出的结果是:*1 *2 *3 #4 #4 #4 涉及到的知识点: 异步、闭包、作用域 setTimeout是一个注册事件,在主程序运行结束前,是不会调用的。 就像为某个div绑定一个点击事件一样,在没点击之前,这个事件是不会被触发的。 这就是一个常见的异步编程的例子。 2、异步编程的方法 Ⅰ、回调函数 假设有 f1(); f2(); 两个函数,其中f2()在等待f1()的执行结果。 function f1(f2){ setTimeout(function(){ f2(); }, 1000); } 代码执行顺序:f1(f2); 优点:f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行 缺点:不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),而且每个任务只能指定一个回调函数 Ⅱ、事件监听 f1.on('done', f2);//jQuery写法,当f1发生done事件,就执行f2 function f1(){ setTimeout(function () { f1.trigger('done');//执行完成后,立即触发done事件 }, 1000); } 优点:可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化 缺点:整个程序都要变成事件驱动型,运行流程会变得很不清晰 Ⅲ、发布/订阅 jQuery.subscribe("done", f2);//f2向jQuery订阅"done"信号 function f1(){ setTimeout(function () { jQuery.publish("done");//f1执行完成后,向jQuery发布"done"信号,从而引发f2的执行 }, 1000); } Ⅳ、Promises对象 它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成: f1().then(f2); 对f1进行如下改写: function f1(){ var dfd = $.Deferred(); setTimeout(function () { dfd.resolve(); }, 500); return dfd.promise; } 优点:回调函数变成了链式写法,程序的流程可以看得很清楚,可以指定多个回调函数,如: f1().then(f2).then(f3); f1().then(f2).fail(f3); 缺点:编写和理解,都相对比较难 附几个概念: 一、事件 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。 二、注册事件 注册事件分为属性注册和方法注册。 属性注册:1.内嵌在DOM结构里的属性赋值 HTML: <button onclick="sayHello()">点击</button> JS: function sayHello() { console.log('hello') } 2.通过JS来指定元素对象的属性赋值 document.body.onclick = function (e) { alert("为body注册一个点击事件"); }; 方法注册:1.通过addEventListener()方法注册 说明:在JS中,window、document、HtmlElement等对象可以通过addEventListener()方法注册事件的处理程序。 语法:EventTarget.addEventListener(eventName, eventHandler, |useCapture ) 参数: ①eventName {string} :所要注册的事件名称,不区分大小写。此名称不需要像注册事件属性那样前缀加上"on"。如注册鼠标点击事件,写为click。 ②eventHandler {function | function Object} :函数或者函数对象。事件触发时所需要执行的函数;当使用函数对象多次注册同一事件时,只当注册一遍。 ③useCapture {boolean} 可选 :是否处于捕获阶段,默认为false。 多次注册:addEventListener()方法能为同一个对象的同一事件注册多次。当发生此事件时,注册的处理事件程序将按照注册先后顺序执行。 注意: ①IE9之前的IE的不支持此方法,可使用attachEvent()代替。 ②若使用相同的事件处理程序对象多次注册在同一个事件上,只算注册一次。 例: document.body.addEventListener('click',function(e){ console.log('被点击一'); }); document.body.addEventListener('click',function(e){ console.log('被点击二'); }); document.body.click(); // 输出: 被点击一 被点击二 2.通过attachEvent()方法注册 说明:IE9之前的IE版本可通过此方法注册事件。 语法:EventTarget.attachEvent(eventName, eventHandler) ①eventName {string} :所要注册的事件名称,区分大小写。这里的名称跟事件属性一样,以"on"开头,后面跟着事件名称。如:onclick、onload。 ②eventHandler {function | function Object} :函数或者函数对象。事件触发时所需要执行的函数;当使用函数对象多次注册同一事件时,可注册多次(addEventListener()方法只当注册一次)。 多次注册:attachEvent()方法能为同一个对象的同一事件注册多次。当触发此事件时,也会依次执行。 例: function sayHellow(){ console.log('hello'); } document.body.attachEvent('onclick',sayHellow); document.body.attachEvent('onclick',sayHellow); // sayHellow第二次注册同一事件 document.body.click(); //输出2次sayHellow函数 :hello hello 二、注销事件 JS中,可调用removeEventListener()[注销addEventListener()] 和 detachEvent()[注销attachEvent()] 来注销元素的某个事件指定的处理程序,也可以给事件属性赋值null来注销此事件的所有绑定。 1.removeEventListener(eventName, function Object) 说明:注销通过addEventListener()注册的事件处理程序。 语法:EventTarget.removeEventListener(eventName, eventHandlerObj) 参数: ①eventName {string} :所要注销的事件名称,不区分大小写。此名称不需要像注册事件属性那样前缀加上"on"。如注册鼠标点击事件,写为click。 ②eventHandlerObj {function Object} :函数对象。传入一个函数体是没有效果的。 例: // 注销body click事件的sayHello函数 document.body.removeEventListener('click',sayHello); 2.detachEvent(eventName, function Object) 说明:注销通过attachEvent()注册的事件处理程序。 语法:EventTarget.detachEvent(eventName, eventHandlerObj) 参数: ①eventName {string} :所要注销的事件名称,区分大小写。这里的名称跟事件属性一样,以"on"开头,后面跟着事件名称。如:onclick、onload。 ②eventHandlerObj {function Object} ::函数对象。传入一个函数体是没有效果的。 例: // 注销body click事件的sayHello函数 document.body.detachEvent('onclick', sayHello); 3.取消事件 给对象的事件属性赋值为null,可取消此事件的所有注册过的处理事件程序。 例: // onclick属性赋值为null,相当于注销了onclick事件 document.body.onclick=null; |
参考链接: http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html