天天看点

react classname多个_React 全家桶

react classname多个_React 全家桶

此全家桶用到的库有:redux, react-redux, immutable.js, redux-actions, redux-saga,react-router,此外用的是 ES6 语法,给公司后端同学看的一个简单入门和对项目技术栈的了解

React

React 是一个专注 view 层的(UI层)的 JavaScript 库,它比传统的操作 DOM 的 JavaScript 库性能高很多,并且非常灵活,可以与其他框架很好的配合,通过 React 构建组件,使得代码更加容易得到复用。然而 React 本身做的东西比较小,在大型应用中通常要用到它的周边产品

JSX

在 React 中推荐使用 JSX 语法,JSX 是 JavaScript 语法的扩展,它使得组件的构建和数据交互更加简洁和方便,先介绍一下 JSX 语法

1. 书写格式,直接在 JS 里面书写 HTML 标签

let a = <div>welcome div</div>
           

2. 当有多个标签时,需要使用一个元素包裹它,代码可以自由缩进

let a = <div> 
           <div>welcome div</div>
           <span>span</span> 
       </div> 
           

3. 单标记必须闭合

<img />
           

4. 类名用 className, style 必须写成 json 形式

<div style={{width:'100px', height:'200px'}}></div>
           

5. JSX 语法里面写 JS 代码,代码块用 {}

7. 事件名采用驼峰命名法,单词首字母大写

onclick -> onClick
 onchange -> onChange
           
React 开发模式

1. 直接引入文件,react.js 它是是 React 的核心库,react-dom.js 提供与 DOM 相关的功能 babel.min.js 的作用是将 JSX 语法转为 JavaScript 语法

2. 基于webppack

React 语法

定义 React 组件推荐使用 ES6 的语法,ES6 稍后介绍

1. 定义组件

首先用 class 来定义一个组件,组件名称首字母必须大写,继承

React.Component

class Title extends React.Component{ 
	render(){
	    return <h3> welcome React </h3>
	 }
}
           

调用 Title 组件,并把它渲染到页面中中,ReactDOM.render() 方法用于将模板转为 HTML 语言,并插入指定的 DOM 节点

ReactDOM.render(
	       <Title />,
	        document.querySelector('#app')
	)
           

2. 组件的参数

我们给 Title 组件传递一个参数 name,在Title 组件内部就可以通过 this.props.name拿到,props 是只读不能修改的

class Title extends React.Component{ 
	    render(){
                const name = this.props.name
	        return <h3> welcome {name} </h3>
	    }
	}
  ReactDOM.render(
	       <Title name='React'/>,
	        document.querySelector('#app')
	)
           

3. 组件的状态

React 将组件看成一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI ,也就是状态更新时视图跟着更新

class Toggle extends React.Component{
            constructor(props){
                super(props);
                this.state={
                    show:false
                };
            }
            handleClick =() =>{
                this.setState({
                    show:!this.state.show
                });
            }
            render(){
                let showStr = this.state.show ? 'block':'none';
                return (<div>
                    <input onClick={this.handleClick} type="button" value="按钮" />
                    <div className="box" style={{display:showStr}} />
                </div>)
            }
        }
        ReactDOM.render(<Toggle />,document.querySelector('#app'));
           

4. 组件的生命周期

componentWillMount		组件挂载前
   componentDidMount		组件挂载后
componentWillUpdate		组件更新前
componentDidUpdate		组件更新后
componentWillUnmount	        组件卸载
           

此外,React 还提供两种特殊状态的处理函数。

componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
           

异步获取数据一般放在 componentDidMount 生命周期中,此时组件已经完成挂载,加载数据成功之后触发组件重新渲染

5. 组件之间通信

  • 父级 -> 子级,通过 this.props 传递,父级调用子级的时候,给子级传递 msg 参数,如<Child msg={这里父级数据} />,子组件 Child 通过 this.props.msg 可以拿到父级传递过来的数据 ”这里父级数据“
  • 子级 -> 父级,通过回调函数传递参数的形式实现,父级给子级传递一个回调函数,如<Child fnCallBack={这里父级一个函数} />,在子组件 Child 里面执行这个函数,传入参数,this.props.fnCallBack(传入子级数据),这样父级就拿到了子组件传递过来的参数
class Child extends React.Component{
            constructor(props){
                super(props);
                this.state={
                    msg:'from child msg'
                };
            }
            componentDidMount(){
                this.props.fnCallback(this.state.msg);
            }

            render(){
                return (<div>
                    <h3 >我是子级 ->{this.state.msg}</h3>
                </div>)
            }
        }
        class Parent extends React.Component{
            constructor(props){
                super(props);
                this.state={
                    msg:''
                };
            }
            getMsg =(msg) =>{
                this.setState({
                    msg:msg
                });
            }
            render(){
                return (
                   <div>
                      <h3>我是父级 -> {this.state.msg || '没有数据'}</h3>
                      <Child fnCallback={this.getMsg}/>
                   </div>
                 )
            }
        }
        ReactDOM.render(
                <Parent />,
                document.querySelector('#app')
        )
           

6. 表单

通过回调函数获取表单的值,ev.target获取表单元素

class MyInput extends React.Component{
            constructor(props){
                super(props);
                this.state={
                    msg:''
                };
            }
            handleChange = (ev) =>{
                let val = ev.target.value;
                this.setState({
                    msg:val
                });
            }
            render(){
                return (<div>
                    <input type="text" onChange={this.handleChange} />
                    <strong>{this.state.msg}</strong>
                </div>)
            }
        }
           

对 React 的基础认识这里只介绍这么多,更多详细介绍请参考 React 官方文档

ES6

ES6 介绍一些常用的方法,更多内容可以参考 ECMAScript 6 入门

1. 新增声明变量的方法 const, let, class, import

2. 变量的解构赋值:可用于提取 json 对象中的数据如 const { key1, key2 } = this.props

3. 字符串的扩展:(``)模板字符串,其中引入变量用${}

4. 函数的扩展:

  • rest参数 function f(...a){}
  • 箭头函数,f = (参数) => 代码块,箭头函数没有自己的this,而是引用外层的this,如果代码块部分多余一条语句,使用retrun {},如果返回一个对象,用大括号包起来({}),箭头函数大大简化了回调函数:[1,2,3].map(x => x * x)

5. 数组的扩展

  • 数组的扩展运算符 ...,代替apply方法,将数组转为函数的参数
Math.max.apply(null,[14, 3, 77]) 
等同于 Math.max(...[14, 3, 77]) 
等同于 Math.max(14, 3, 77);
           
  • 合并数组[1,2,...more]
  • 数组的深拷贝
const a1 = [1,2];
const a2 = [...a1];
a1[1] = 3;
console.log(a2)} //[1,2]
           
  • 数组的 includes() 方法可代替 indexof()
[1,2,NaN].includes(NaN)  //ture
[1,2,NaN].indexOf(NaN)   //-1   indexOf()内部使用 === 判断
           

6. Set:类似于数组,但成员的值是唯一的

  • 数组去重
const arr = [1,2,3,4,5,5,5];
const set = [...new Set(arr)]; //[1,2,3,4,5]
           
  • 获取两个数组的并集和交集
let a = new Set([1,2,3]);
let b = new Set([3,4,5]);
并集:let union = [...new Set([...a,...b])]   //[1,2,3,4,5]
交集:let intersect = [...new Set([...a].filter(x => b.has(x)))];  //[3]
           

tips:通过数组的辅助迭代器也可以实现

forEach() 会遍历数组中所有的值并忽略回调函数返回的值

every() 会一直运行直到回调函数返回 false

some() 会一直运行直到回调函数返回 true

every() 和 some() 中特殊的返回值和 for 循环中的 break 语句类似,它们会提前终止遍历

const a = [1,2,3,4,5];
const b = [1,2,3];
交集:const ab = a.filter(ca => b.some(cb => cb === ca)) //[1,2,3]
差集:const a_b = a.filter(ca => !b.some(cb => cb === ca)) //[4,5]
           

7. promise:一个对象,获取异步操作的消息

var promise = new Promise(function(resolve,reject){
		//...code
		if(/*异步函数调用成功*/){
			resolve(value) //异步操作的结果,作为参数传递出去
		}else{
			reject(error)
		}
	})
	promise.then(function(){value},function(){error})
           

8. Iterator: 遍历器,为各种数据结构提供一个统一的,简便的访问接口,部署在Symbol.iterator属性上面

  • 原生具备Iterator接口的数据结构有:Array,Map,Set,String,TypedArray,函数的arguments对象,NodeList对象。
  • - Iterator接口主要供 for...of消费,for..of 可代替数组实例的 forEach,且可与continue,break,return配合使用,for...in 循环读取键名,for...of 循环读取键值

9. Generator 函数:是一个状态机,封装了多个内部状态,执行返回一个遍历器对象,只有调用 next() 方法才会遍历下一个内部状态

function* generator(){
	yeild 表达式
	yeild ..
}
           

10. async函数:返回一个promise对象,可用then方法指定下一步操作

async function(){
	await 表达式
	await ..
}
           

immutable.js

提供了通过结构共享实现不可变的、持久的集合:

  • 不可变:一个集合一旦创建,在其他时间是不可更改的
  • 持久的:新的集合可以基于之前的结合创建并产生突变,原来的集合在新集合创建之后仍然是可用的
  • 结构共享:新的集合尽可能通过之前集合相同的结构创建,最小程度地减少复制操作来提高性能

不可变性使得追踪改变非常容易,改变会产生新的对象,因此我们仅需要检查对象的引用是否改变,不可变数据提供了一种更简单的方式来追踪对象的改变,这正是我们实现

shouldComponentUpdate

所需要的。这将会提供可观的性能提升。参考 React 优化性能

将javascript对象转化为不可变数据类型,提供了List, Stack, Map, OrderedMap, Set, OrderedSet, Record等7种不可变的数据结构,代替深拷贝,但不是基于递归复制,性能高很多,详细介绍参考 官方文档

  1. fromJs(),将javascript的Object,Array转化为Map和List,与javascript Object不同的是,Immutable Maps的键可以是任意类型的参数
  2. toJS(),将immutable深度转换,toJSON()相对为浅转换,toArray(),转换为数组,toObject(),转换为对象
  3. get(key),set(key,value),通过键名获取和设值方法,getIn(keypath),setIn(keypath,value),通过键或索引的路径获取和设置嵌套集合的值,另外还有update(key,updater),updateIn()

Redux

Redux 是用来解决component -> action -> reducer -> state 的单向数据流转的问题。

Redux 是一个提供可预测化状态管理的容器,主要包含store,reducer,action三个概念,应用中的 state 以对象树的形式存储在 store 中,state是只读的,惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象

通过 dispatch action来改变 state,描述 action如何改变 state 的函数叫 reducer,更多参考 Redux 中文文档

1. action

  • 可参考action设计规范, type,payload,error.meta,其中 type 是必须的
  • 异步action,通过中间件实现

2. reducer

  • reducer必须是纯函数
  • 可以拆分成多个reducer,通过combineReducers合并

3. store

  • 单一Store
  • 根据reducer创建 store, createStore(reducer,initialState)
this.props.dispatch({
      type: 'GETDATA',
      payload: data
 })
           

redux-actions

简化reducer处理函数,handleActions(reducerMap, defaultState)

import { handleActions } from 'redux-actions'
import { fromJS } from 'immutable'

const initialState = fromJS({
	loading: true,
	data: {},
})

const reducer = handleActions(
	{
	  ['GETDATA']: (state, action) => {
		return state.set('data', fromJS(action.payload))
                            .set('loading',false)
	  }
	},
	initialState
)

export default reducer
           

redux-saga

可以把所有的业务逻辑都放在 saga 里,那么 reducer,action.component 可以很纯粹,只干他们原本要做的事情

sagas 是用于处理 redux 的异步操作的中间件,通过 genarator 函数创建,每个任务通过yeild Effects 完成,Effects是javascript对象,包含了sagas middleware执行的信息,Redux-saga 中文文档

1. 创建一个中间件,将 sagas 与redux store建立连接,方法为createSagaMiddleware(...sagas),其中sagas为 Generator 函数列表的数组

const sagaMiddleware = createSagaMiddleware(...sagas)
  const store = createStore({
  		reducer,
  		initialState,
  		applyMiddleware(sagaMiddleware)
	})
           

2. saga辅助函数, takeEvery(pattern,saga,...args),在发起的action与pattern匹配时,触发saga,允许并发

import {takeEvery} form 'redux-saga'
  function* watch(){
  	yeild*   takeEvery('FETCH_USER',fetchUser)
  }
           

takeLatest(pattern,saga,...args), 只会触发最后那次Action, 防止多次点击提交

3. Effect创造器

  • take(pattern),middleware 等到 action 匹配 pattern
  • put(action),异步发送action到store
  • call(fn,...args),middleware调用fn(...args),fn为一个generator函数或者返回一个promise的普通函数
  • fork(fn,...args),无阻塞调用,返回一个task
  • cancel(task),取消之前的fork任务
  • select(selector,...args),通过selector获取store state的数据,如果参数为空,将获取整个store state
import { call, put} from 'redux-saga/effects'
import { takeEvery } from 'redux-saga'

function* getUserData() {
  try {
    const res = yield call(get,'http://...')  //get为一个返回 promise 的普通函数
    if (res.status !== 'success') {
      //错误处理
      return
    }
    const userData = res.content
    yield put({
      type: 'global/set-user',
      payload: userData || {}
    })
  } catch (error) {
    console.log(error)
  }
}

function* defaultSaga() {
  const watchers = yield [
    takeEvery('global/getUserData', getUserData),
  ]
  return
}

export default defaultSaga
           

React-redux

react-redux 用于连接react 和 redux, 使得react 能够访问redux的store

  1. <Provider/>

    组件,能够使你的整个app访问到

    Redux store

    中的数据:
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);
           

2.

connect

方法能够让你把组件和

store

连接起来。

function mapStateToProps(state) {
  return {
    data: state
  };
}

function mapDispatchToProps(dispatch) {
  return {
    dispatch
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(App);
           

React Router

React Router 保持 UI 与 URL 同步。它拥有简单的 API 与强大的功能例如代码缓冲加载、动态路由匹配、以及建立正确的位置过渡处理 ,详细参考 React Router 中文文档 ,英文文档

history 监听浏览器地址的变化,并解析url转化为 location 对象,然后 router 使用它匹配到路由,渲染对应的组件

动态路由:

Route可以定义 getChildRoutes, getIndexRoute, getComponents 这几个异步执行函数,React Router 会逐渐匹配 URL 并只加载对应页面所需的路径配置和组件

  • 获取URL参数:

1.通过 params 获取

<Link to='/inbox/message/:id' />
 this.props.params.id
           

2. 通过 location 的 query 对象获取

hashHistory.push(/fool?bar=baz)
hashHistory.push(/fool,query: { bar: ' baz'} )
 <Link to={{ path : ' /fool ' , query : { bar : 'baz' }}}>
this.props.location.query.bar 
           

3. 通过 location 的 state 对象获取,state 传递的参数不会在地址栏公开

hashHistory.push(/fool,state: { bar: ' baz'} )
this.props.location.state.bar 
           
  • 跳转前确认

每个路由都有

Enter

Leave

钩子,用户进入或离开该路由时触发

下面是一个常见的应用,在用户离开页面时提示用户确认是否离开

routerWillLeave(),返回 false 取消跳转,否则返回一个字符串,提示用户

componentDidMount() {
      this.props.router.setRouteLeaveHook(
        this.props.route, 
        this.routerWillLeave
      )
    }
    routerWillLeave = (nextLocation) => {
      if (!this.state.isSaved)
        return '确认要离开?';
    }
           

以上初步罗列了部分知识点,后续会慢慢补充知识点和实例