简介
React起源于Facebook的内部项目,用来架设Instagram的网站;
官网:React – A JavaScript library for building user interfaces;
使用 JSX语法 创建组件,实现组件化开发,通过 diff算法 和 虚拟DOM 实现视图的高效更新;
跨平台:JSX --> HTML、JSX --> ios/android、JSX --> VR、JSX --> 物联网
虚拟DOM原理
核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作;
在DOM的基础上建立了一个抽象层,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中;
缺点:首次渲染大量DOM时因为多了一层虚拟DOM的计算,会比innerHTML插入方式慢。
生命周期的方法
1)componentWillMount 组件被挂载到页面之前调用(在render()之前被调用)
无法获取页面中的DOM对象,可以调用 setState() 方法来改变状态值,发送请求获取数据;
2)componentDidMount 组件已经挂载到页面中(在render之后执行)
可以进行DOM操作,可以通过this.getDOMNode()来进行访问,比如:获取到组件内部的DOM对象。可以发送请求获取数据。可以通过 setState() 修改状态的值。
注意:在这里修改状态会重新渲染;
3)componentWillReceiveProps 组件接收到新的props前触发这个方法,参数:新的props。可以通过 this.props 获取到上一次的值。注意:修改state不会触发该方法
4)shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用,componentWillUpdate之前执行,根据返回的布尔值决定是否渲染组件
参数:第一个参数-最新属性对象,第二个参数-最新状态对象
5)componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。参数:最新的属性和状态对象。注意:不能修改状态, 否则会循环渲染
6)componentWillUnmount 在卸载组件的时候,执行清理工作,比如:清除定时器 clearInterval(timer),清除componentDidMount创建的DOM对象
目录
node_modules为项目依赖目录
public为静态资源目录
package.json为包配置文件
src为开发目录,项目源代码就在这个目录下:
1)index.js 是项目的入口文件
2)App是根组件
3)registerServiceWorker.js 可以使项目离线访问
路由
// HashRouter:有#号
// BhxBrowser:没有#号
// Switch:如果匹配到一个就跳出,类似break
// Link:跳转页面,类似vue的router-link
// exact:完全匹配路由
接收参数:
1)接收参数方案一:
如果路由的path= “/news/details/:id”用以下方式接收参数:
this.props.match.params.id
2)接收参数方案二:
接收pushPage ()方法传过来的值
this.props.location.query.id //这个接收方式看似很好,但是页面不能刷新,如果刷新便找不到id
3)接收参数方案三: function,js (推荐)
使用方法:
var get=localParam(this.props.location.search);
var id=get.search.id;
//返回
this.props.history.goBack();
this.props.history.push(path);
this.props.history.replace(path);
导航组件
1) 导航链接,to: 需要定位的页面;
2) 当url匹配上时,可以为当前链接添加样式属性,添加 activeStyle属性;
3) 用来实现路由重定向;
4) 组件用来选出第一个匹配成功的路由;
跨域问题
配置proxy(代理)解决跨域问题:
现在package.json里面配置如下:
"proxy":{
"/proxy": {
"target": "商城", // 接口域名
//secure: false, // 如果是https接口,需要配置这个参数
"changeOrigin": true, //是否跨域
"pathRewrite": {
"^/proxy": "" //需要rewrite重写
}
}
}
单页应用和多页应用
1) 什么是单页应用
单页应用简称SPA
整个webapp就一个html文件,里面的各个功能页面是JavaScript通过hash,或者history api来进行路由,并通过ajax拉取数据来实现响应功能
饿了么 饿了么的移动端网站是典型代表
2.)多页应用
每一次页面跳转的时候,后台服务器都会给返回一个新的html文档,这种类型的网站也就是多页网站,也叫做多页应用
3)比较
单页应用:页面切换快首屏时间慢,SEO差
多页应用:首屏时间快,搜索引擎优化效果好(SEO好),切换慢
Redux
Redux 是 JavaScript 状态容器, 提供可预测化的状态管理。
Redux 的三大基本原则;
单一数据源,state 是只读的,只能通过触发action修改state,使用纯函数来执行修改。
使用store 统一管理状态:
1)组件通过 dispatch 将 state 传入 store;
2)组件通过 subscribe 从 store 获取到 state 的改变;
将Redux理解成一个仓库:
1)state
redux中只维护一个store树, 这个树下存储各个模块的state;
2)dispatch
表明触发修改state的操作,且只能通过dispatch触发修改。 它的参数是一 个action;
3)action
action表示当前dispatch (操作)的类型和载荷(数据) (payload) ;
通过动作来修改state的值,是store数据的唯一来源;
action是一个js对象,必须有一个字段type,如:{type:‘change_theme’,color:‘red’};
4)reducer
是一些纯函数,用来修改state的, 接收两个参数state和action, 生成一 个新的state返回;
// 纯函数: 不使用外界网络或数据库调用,返回的值完全取决于其参数的值,调用具有相同的参数集的一个纯函数始终返回相同的值,如:
var someReducer = function(state, action) { … … return state;}
Redux的工作流程:
1)首先,用户发出 Action;
store.dispatch(action);
2)然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State ;
let nextState = todoApp(previousState, action);
3)State 一旦有变化,Store 就会调用监听函数;
store.subscribe(listener);
4)listener可以通过store.getState()得到当前状态;
store.getState();
其他
1)若是有html标签-必须使用dangerouslySetInnerHTML
2)提示处理,添加这个就不会再提示无关警告
/eslint-disable/
3)时间
this.setState({
date: (new Date()).toLocaleTimeString(),
year: (new Date()).toLocaleDateString()
})
4)如果想使用传统的class来获取样式,需要下载安装react-html-attrs插件(暂时不需要)
$ sudo npm install babel-plugin-react-html-attrs --save-dev
5)React是单页面应用,引用CSS样式默认都是全局的,这样会引起样式冲突,降低性能。(推荐)
React需要使用style-loader、 css-loader这两个插件来解决。
$ sudo cnpm install --save-dev style-loader css-loader
6)组件缓存
vue中有keep-alive进行页面缓存,react提倡尽可能少的api以减少开发者的使用成本,评价较高的对应插件(这两种插件不仅仅在做页面缓存时有用,在登录拦截,路由配置拆分的时候也用的到):
React Keep Alive git地址:https://github.com/StructureBuilder/react-keep-alive
React-Keeper git地址:https://github.com/vifird/react-keeper
其它帖子地址:
react.js - React-Keeper 前端路由缓存 存储状态(大部分转)_个人文章 - SegmentFault 思否
7)路由传参
pushPage(path) {
this.props.history.push(path)
}
// function.js处理的search乱码
let id=localParam(this.props.location.search).search.id
// decodeURIComponent 解码-汉字
let title=decodeURIComponent(localParam(this.props.location.search).search.title)