React 技术分享

5次阅读

共计 4403 个字符,预计需要花费 12 分钟才能阅读完成。

1. react 介绍 和 想法

A declarative, efficient, and flexible JavaScript library for building user interfaces
react 是一个专注于 UI 的库
状态机 输入 => 组件 => 输出
组件化 react 组件映射 为原生 android 组件 原生 ios 组件 react vr

2. jsx 语法
JSX 就是 Javascript 和 XML 结合的一种格式,要使用需要在 babelrc 里配置, Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用
// 最外层必须有一个元素包裹
<div>hello world!</div>

// 属性都要驼峰
<div className=”haha” ></div>

// 样式
<div style={{marginTop: ’10px’}}></div>

// 变量
<div> {user.name}</div>

// 事件
<button onClick={}> click me </button>

// 遍历
<ul>
{
list.map(
({name, value}) => <li key={name} value={value}>{name}</li>
)
}
</ul>

// 展开对象
const props = {name: “tom”}

<div {…props}></div>
3 虚拟 DOM 和 diff 算法
a. 虚拟 DOM(Virtual DOM)机制:对于每一个组件,React 会在内存中构建一个相对应的 DOM 树,基于 React 开发时所有的 DOM 构造都是通过虚拟 DOM 进行,每当组件的状态发生变化时,React 都会重新构建整个 DOM 数据,然后将当前的整个 DOM 树和上一次的 DOM 树进行对比,得出 DOM 结构变化的部分 (Patchs),然后将这些 Patchs 再更新到真实 DOM 中 b. 两个不同类型的元素会产生不同的树 (根元素不同结构树一定不同)c. 开发者可以通过 key 属性指定不同树中没有发生改变的子元素 d. diff 算法的核心就是同级比较
4. state 和 props

react 数据是单向流动的 数据自顶向下流动 ,
props 是传递来的参数,从父级组件向子组件传递的数据, 是只读的
state 是自己的内部状态
在 react 更新生命周期 setState 会导致死循环

// 默认参数
Main.defaultProps = {
list: []
}

// setState 是异步的
this.setState((prevState,props) => ({
text: prev.text + “-ha”
}))
5. 生命周期
Note: 父子组件的挂载顺序,更新顺序
6 函数式编程

函数式编程, 函数作为一等公民,而不是类和对象
纯函数 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数
高阶函数 函数的参数可以是函数,返回值也可以是函数 , 如数组的

forEach map filter some reduce ,setTimeout setInterval 等
柯里化是指这样一个函数 (假设叫做 createCurry),他接收函数 A 作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数 A 的剩余参数
6 无状态组件
顾名思义,它没有 state,接收 props,它是一种只负责展示的纯组件 使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量,多写无状态组件
function HelloComponent(props) {
return <div>Hello {props.name}</div>
}

ReactDOM.render(<HelloComponent name=”marlon” />, mountNode)
7 使用 fragment 碎片 Jsx 要求返回的元素,必须有东西包裹, 使用碎片可以减少一层 DOM
<React.Fragment>
<td>Hello</td>
<td>World</td>
</React.Fragment>
// 可以简写为
<>
<td>Hello</td>
<td>World</td>
</>
8 使用 context
Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性,React.createContext 创建一个 context,一个 context 包含 provider(数据提供者), comsumer(数据消费者), Provider 有一个 value 参数,用来覆盖创建时的默认值
// 创建一个 theme Context, 默认 theme 的值为 light
const ThemeContext = React.createContext (‘light’);

function ThemedButton(props) {
// ThemedButton 组件从 context 接收 theme
return (
<ThemeContext.Consumer>
{theme => <Button {…props} theme={theme} />}
</ThemeContext.Consumer>
);
}

// 中间组件
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}

class App extends React.Component {
render() {
return (
<ThemeContext.Provider value=”dark”>
<Toolbar />
</ThemeContext.Provider>
);
}
}
9. mobx
推荐一个 react 模块的目录结构
/states 状态
/(widgets|components) 各类组件、弹窗等
index.js
index.less
service 建议放在 config 里,全局统一

Computed 用于生成计算数据,autorun 类似用来监听某一数据改变而作出反映
import {action, observable ,autorun} from ‘mobx’;
import StateAdd from “./add”

class State {
constructor(){
this.$add = new StateAdd(this);
}
// 显示
@observable show = false;

// query
@observable query = {
trade: null,
type: 1
}

/**
* @name 获取列表
*/
@action getList = () => {

}

}

const instance = new State();

autorun(() => {
if(instance.show){
console.log(“ 打开弹窗了 ”)
}
})

export default instance
10 高阶组件
主要有两种实现方式属性 proxy、继承实现 通常使用装饰器模式调用, 常见的有 mobx 的 @observer, react-router 的 withRouter 等
—— 属性 proxy 实现如下
import React from “react”
export default class extends React.Component {
render = () =>
<div>
<div>
<Hoc1_text name={‘Hoc1_text’}/>
</div>
<div>
<Hoc2_text />
</div>
</div>
}

class Text1 extends React.Component {
render = () =>
<div>
this is simple text <br/>
{this.props.name}
</div>
}

/**
* @name 操作 props
*/
function Hoc1(Component){
return class extends React.Component {
render = () =>
<div className=’hoc1′>
<Component {…Object.assign({} , this.props, {gen : ‘111’})}/>
</div>
}
}

const Hoc1_text = Hoc1(Text1);

class Text2 extends React.Component {
render = () =>
<div>
<input type=”text” value={this.props.value} onChange={this.props.change}/>
</div>
}

/**
*@name 抽离 state
*/
function Hoc2(Component){
return class extends React.Component {
state = {
value: ’11’
}
change = e => {
this.setState({
value: e.target.value
})
}
render = () =>
<div>
<Component value={this.state.value} change={this.change}/>
</div>
}
}

const Hoc2_text = Hoc2(Text2);

function Hoc3(Component){
return class extends React.Component {
getRef = _ref => {
this.refs = _ref;
}
render = () =>
<div>
<Component ref={this.getRef}/>
</div>
}
}

—— 继承组件 实现如下 ——-
class Text extends React.Component {
render(){
return (
<div>
this is text
</div>

)
}
}
// 生命周期可以覆盖掉
const hoc2 = Component => {
return class NewHoc extends Component {
static displayName = `NewHoc-${Component.displayName || Component.name}`
render(){
const element= super.render();
console.log(element)
const style = {
color: element.type === ‘div’ ? ‘red’ : ‘green’
}
const newProps = {…this.props, style}
return React.cloneElement(element, newProps, element.props.children)
}
}
}

const NewCom = hoc2(Text)
11 注意事项

React 组件名字大写
不能直接修改 state props
更新函数里不能做状态操作 (死循环)
多用无状态组件
多用 pureComponent React.PureComponent 通过 prop 和 state 的浅对比来实现 shouldComponentUpate()。
代码清晰,一目了然,注释写好
过度封装不如不封装
使用 ImmutableJS 处理数据提升性能

正文完
 0