React.Js实战
需求来源
前端框架引入地图
初识
在React与Vue框架选择中,非常犹豫,React有成熟的社区和面对对象的抽象思想,vue则是轻量级的代表,结合了Angular和React的优势,对于新手用此入门甚佳。
- React对大型应用的优势和完备的测试体系,可作为进阶学习之用。
阮一峰教程:http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html
前端开发的实质
前端开发是与工程化紧密相连的,甚至是与UED等用户体验等艺术性相背离的,目前没有发现能在艺术和工程都能协调完美的人。
前端开发面对的是复杂的组件,表现在管理和抽象复杂业务的能力,组件实质就是状态的集合,这和服务器端的服务复杂交互、治理,是同出一脉。
准备工作
在学习React之前,先保证有node,npm相关的经验,不熟悉请参考本人另一篇文章——VueJs实战。
脚手架
项目的基本模板,对引入的包和开发配置都基本完备,直接可以开始开发。
阮一峰脚手架下载:https://github.com/ruanyf/react-babel-webpack-boilerplatejsx语法
主要包括组件创建,组内通信,jsx内使用方法等
阮一峰demo:https://github.com/ruanyf/react-demos使用css
主要是内联,嵌入,外联三种形式,注意react的class需写作className。
参考文章:htps://blog.csdn.net/daxiazouyizou/article/details/79758558创建组件
创建组件有多种方法,目前版本代码可读性最高的是import React,{Component} from 'react'; export default class App extends Component { render() { return ( <div><div/> ); } }
编码规范要求组件首字母大写,驼峰式。
组件多种创建方式:https://www.cnblogs.com/Unknw/p/6431375.html
组件通信
react的单向数据模型,要求只能父组件给子组件传数据。
这点与angular和vue不同,也是其强大的优势之一。
双向数据模型,能提高编程的灵活性,但也导致了组件通信的混乱和代码规范的难以制定,所以React才能成为大型项目的无冕之王。父组件 import Son from './son'; export default class Dad extends Component { render() { var message = "God bless U!" return ( <Son mess = {message}><Son/> ); } } 子组件 export default class Son extends Component { render() { var message = this.props.mess return ( <div>{message}<div/> ); } }
组件数据分为state和pros两种,
state为组件内数据,只读,无法分享,
pros为父组件串入的数据。
组件通信参考文章:https://segmentfault.com/a/1190000006831820
共享数据
Redux是React的拓展插件,是Vuex的被模仿对象。
react的组件复杂的情况下,其沟通就有了瓶颈,组件层级到了很深,要获取数据必须逐层往上获取,为了解决这个问题,redux产生了。
redux主要是两个概念,第一个概念是用store作为全局状态管理,通过mapStateToProps和connect方法将状态放于组件,又能通过组件的getContext获取store状态,实现数据共享;
另一个概念是组件的变化对应状态的变化,使用事件驱动模型来控制状态达到控制组件目的,action为状态更改事件,dispatch来触发事件,reducer来分发事件,redux-thunk实现异步事件。
阮一峰redux教程:
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html国际化
根据语言环境,选择对应国际化。
react-intl库提供了IntlProvider来包装需要国际化的组件,在组件内使用 《FormattedMessage id= />来使用。
参考地址:https://juejin.im/post/59f96d7ef265da430f316997路由设置
前端路由其实是根据url进行location对象的页面跳转操作。
react-router库提供Router来管理URL,内部组件Route的path属性来进行url的匹配,来控制跳转和组件变化。
阮一峰react-router教程:
http://www.ruanyifeng.com/blog/2016/05/react-router.html测试
可使用官方的测试工具库或第三方库Enzyme。
阮一峰react测试教程:http://www.ruanyifeng.com/blog/2016/02/react-testing-tutorial.html
项目实战
main.jsx为入口,引入了redux实现数据共享,react-intl实现国际化,各类中间件和第三方插件引入,只包含app这个组件,代码如下
import React from 'react';
import ReactDOM from 'react-dom';
import intl,{IntlProvider,addLocaleData} from 'react-intl'
import App from './components/App';
import getI18n from 'root/assets/i18n/i18n'
import {Provider} from 'react-redux'
import {applyMiddleware,createStore} from 'redux'
import reducer from './store/reducer'
import {createLogger} from 'redux-logger'
import InitState from './store/initState'
import thunk from 'redux-thunk'
import promise from 'redux-promise'
//引入外部第三方插件
import 'root/business/lib/index'
/*** 导航页
*/
const logger = createLogger();//中间件,日志
let store = createStore(
reducer,
InitState,
applyMiddleware(thunk,promise,logger)
);//创建redux状态管理,中间件分别为支持异步,支持promise和日志
let language = 'zh-CN';//默认中文
let i18n = getI18n(language);
addLocaleData(...i18n.data);//国际化
ReactDOM.render(
<Provider store={store}>
<IntlProvider locale={i18n.locale} messages={i18n.messages} formats={i18n.formats}>
<App />
</IntlProvider>
</Provider>
,
document.body.appendChild(document.createElement('div'))
);
- UI组件
- 入口
- app
app包含右侧栏和上边栏两部分,右侧为菜单,上边为标题 - 菜单
component/bar/sideBar.jsx通过遍历business/menu/menu.js提供的模拟数据,创建元素,其含子元素sideBarIcon(菜单按钮)和sideBarTitle(展示栏) - 标题栏
component/bar/topBar.jsx通过遍历business/toolbar/buttons.js提供的模拟数据,创建元素,其含子元素topBarButton(标题按钮)和topBarList(标题列表) - 展示栏
component/bar/sideBarTitle.jsx展示菜单的名称和返回主菜单按钮
- 组件交互
- 菜单与标题栏、展示栏
点击菜单,发出store/actionType.js的menu.hover事件,通过redux分发到store/reducer.js,PageReducer、TitleReducer和ToolReducer根据这一事件,改变全局state的PAGE、TITLE、TOOL属性,component/bar/sideBarTitle.jsx的mapStateToProps检测到state变化,重新调用类的render,刷新了dom树,展示进入的菜单名称和按钮,component/bar/sideBar.jsx也刷新了页面,隐藏掉菜单,进入对应菜单的页面,component/bar/topBar也相应改变了。
点击返回菜单按钮,则发出menu.back事件,reducer改变redux的state,触发各界面刷新dom。
- 菜单与标题栏、展示栏