react - JSX
React 背景介绍
React 入门实例教程
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
什么是React
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
用来构建UI的 JavaScript库 React 不是一个 MVC 框架,仅仅是视图(V)层的库
特点
- 1 使用 JSX语法 创建组件,实现组件化开发,为函数式的 UI 编程方式打开了大门
- 2 性能高的让人称赞:通过
diff算法和虚拟DOM实现视图的高效更新 - 3 HTML仅仅是个开始
为什么要用React
1 使用组件化开发方式,符合现代Web开发的趋势 2 技术成熟,社区完善,配件齐全,适用于大型Web项目(生态系统健全) 3 由Facebook专门的团队维护,技术支持可靠 4 ReactNative - Learn once, write anywhere: Build mobile apps with React 5 使用方式简单,性能非常高,支持服务端渲染 6 React非常火,从技术角度,可以满足好奇心,提高技术水平;从职业角度,有利于求职和晋升,有利于参与潜力大的项目
React中的核心概念
- 1 虚拟DOM(Virtual DOM)
- 2 Diff算法(虚拟DOM的加速器,提升React性能的法宝)
虚拟DOM(Vitural DOM)
React将DOM抽象为虚拟DOM,虚拟DOM其实就是用一个对象来描述DOM,通过对比前后两个对象的差异,最终只把变化的部分重新渲染,提高渲染的效率
为什么用虚拟dom,当dom反生更改时需要遍历 而原生dom可遍历属性多大231个 且大部分与渲染无关 更新页面代价太大
VituralDOM的处理方式
- 1 用 JavaScript 对象结构表示 DOM 树的结构,然后用这个树构建一个真正的 DOM 树,插到文档当中
- 2 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
- 3 把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了
Diff算法
当你使用React的时候,在某个时间点 render() 函数创建了一棵React元素树,
在下一个state或者props更新的时候,render() 函数将创建一棵新的React元素树,
React将对比这两棵树的不同之处,计算出如何高效的更新UI(只更新变化的地方)
有一些解决将一棵树转换为另一棵树的最小操作数算法问题的通用方案。然而,树中元素个数为n,最先进的算法 的时间复杂度为O(n3) 。 如果直接使用这个算法,在React中展示1000个元素则需要进行10亿次的比较。这操作太过昂贵,相反,React基于两点假设,实现了一个O(n)算法,提升性能:
-
React中有两种假定:
1 两个不同类型的元素会产生不同的树(根元素不同结构树一定不同)
2 开发者可以通过key属性指定不同树中没有发生改变的子元素
JSX的注意点
注意 1: 如果在 JSX 中给元素添加类, 需要使用 className 代替 class
类似:label 的 for属性,使用htmlFor代替
注意 2:在 JSX 中可以直接使用 JS代码,直接在 JSX 中通过 {} 中间写 JS代码即可
注意 3:在 JSX 中只能使用表达式,但是不能出现 语句!!!
注意 4:在 JSX 中注释语法:{/* 中间是注释的内容 */}
React组件
React 组件可以让你把UI分割为独立、可复用的片段,并将每一片段视为相互独立的部分。
- 组件是由一个个的HTML元素组成的
- 概念上来讲, 组件就像JS中的函数。它们接受用户输入(
props),并且返回一个React对象,用来描述展示在页面中的内容
React创建组件的两种方式
- 1 通过 JS函数 创建(无状态组件)
- 2 通过 class 创建(有状态组件) 函数式组件 和 class 组件的使用场景说明:
1 如果一个组件仅仅是为了展示数据,那么此时就可以使用 函数组件
2 如果一个组件中有一定业务逻辑,需要操作数据,那么就需要使用 class 创建组件,因为,此时需要使用 state
JavaScript函数创建
- 注意:1 函数名称必须为大写字母开头,React通过这个特点来判断是不是一个组件
- 注意:2 函数必须有返回值,返回值可以是:JSX对象或
null - 注意:3 返回的JSX,必须有一个根元素
- 注意:4 组件的返回值使用
()包裹,避免换行问题
function Welcome(props) {
return (
// 此处注释的写法
<div className="shopping-list">
{/* 此处 注释的写法 必须要{}包裹 */}
<h1>Shopping List for {props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
</ul>
</div>
)
}
ReactDOM.render(
<Welcome name="jack" />,
document.getElementById('app')
)
给组件传递数据 - 父子组件传递数据
- 组件中有一个
只读的对象叫做props,无法给props添加属性 - 获取方式:函数参数
props - 作用:将传递给组件的属性转化为
props对象中的属性
state
作用:用来给组件提供组件内部使用的数据 注意:只有通过class创建的组件才具有状态 注意:状态是私有的,完全由组件来控制 注意:不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!
可以将组件内部使用但是不渲染在视图中的内容,直接添加给 this 注意:不要在 render() 方法中调用 setState() 方法来修改state的值
但是可以通过 this.state.name = 'rose' 方式设置state(不推荐!!!!)
组件生命周期函数总览
- 组件的生命周期包含三个阶段:创建阶段(Mounting)、运行和交互阶段(Updating)、卸载阶段(Unmounting)
React 单向数据流
- React 中采用单项数据流
- 数据流动方向:自上而下,也就是只能由父组件传递到子组件
- 数据都是由父组件提供的,子组件想要使用数据,都是从父组件中获取的
- 如果多个组件都要使用某个数据,最好将这部分共享的状态提升至他们最近的父组件当中进行管理
- 单向数据流
- 状态提升
react中的单向数据流动: 1 数据应该是从上往下流动的,也就是由父组件将数据传递给子组件 2 数据应该是由父组件提供,子组件要使用数据的时候,直接从子组件中获取
组件通讯 父 -> 子:props
子 -> 父:父组件通过props传递回调函数给子组件,子组件调用函数将数据作为参数传递给父组件
兄弟组件:因为React是单向数据流,因此需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的props
React中的状态管理: flux(提出状态管理的思想) -> Redux -> mobx
Vue中的状态管理: Vuex
简单来说,就是统一管理了项目中所有的数据,让数据变的可控
redux
状态管理工具,用来管理应用中的数据
核心
Action:行为的抽象,视图中的每个用户交互都是一个action
比如:点击按钮
Reducer:行为响应的抽象,也就是:根据action行为,执行相应的逻辑操作,更新state
比如:点击按钮后,添加任务,那么,添加任务这个逻辑放到 Reducer 中
1 创建State
Store:
1 Redux应用只能有一个store
2 getState():获取state
3 dispatch(action):更新state