React框架
目录
React 的起源和发展
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
React 的出发点
用于开发数据不断变化的大型应用程序(Building large applications with data that changes over time)
与传统MVC的关系
React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可MVC开发模式;React 构建页面 UI 的库。可以简单地理解为,React 将将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,就成了我们的页面
React Fiber
在react 16之后发布的一种react 核心算法,React Fiber是对核心算法的一次重新实现(官网说法)。之前用的是diff算法。
React Fiber的方法其实很简单——分片。把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。
构建React简易环境
react开发需要引入多个依赖文件:react.js、react-dom.js,分别又有开发版本和生产版本
react.js 帮助我们创建React对象,帮助我们创建组件等功能
react-dom.js 中有ReactDOM对象,渲染组件的虚拟dom为真实dom
在编写react代码的时候需要大量使用jsx代码,需要编译后使用:
- 浏览器端编译,通过引入browser、babel等引入的script内的代码做编译
- 利用webpack等开发环境进行编译,将编译好的文件引入到应用中
实现一个简单的例子
<!--引入react的核心包-->
<script src="./js/react.development.js"></script>
<!--引入开发web的包-->
<script src="./js/react-dom.development.js"></script>
<!--引入解析jsx的包-->
<script src="./js/babel.js"></script>
<script type="text/babel">
ReactDOM.render(<h2>hello world</h2>,
document.getElementById("box"))
</script>
jsx的原理
jsx 相当于一种语法糖,相当于 js+XML
原理就是通过
React.createElement(tag,{attrs},content)
=> 相当于底层创建了js内存对象(虚拟dom)
=>ReactDOM.render()
jsx 的一些注意事项
- jsx ==> js + xml
- 有且只能由一个根元素
- 因为借鉴了xml的语法规范,标签必须要闭合(特别注意单标签)
- class ==> className,由于class是保留字,所以在jsx中要改成className
- jsx里面的事件名需要改成驼峰式写法,例如onclick => onClick
- jsx 里面的内联样式
style={{backgroundColor:'yellow'}}
let a =
<div>
<p>我是p标签内的文字</p> {/*我是p标签内的文字*/}
<p>{1+1}</p> {/*2*/}
<p>{true}</p> {/*空*/}
<p>{false+1}</p> {/*1*/}
<p>{[1,2,3,4,5]}</p> {/*12345*/}
<p>{undefined}</p> {/*空*/}
{/*<p>{{}}</p>*/} {/*报错*/}
</div>
ReactDOM.render(a, document.querySelector('#box'))
Boolean | undefined | null 不会被渲染出来
数组会转成字符串的形式出现
直接渲染对象的话会报错
遍历数组
let arr = ['aa','bb','cc']
let a =
<ul>
{arr.map((item, index) => {
return <li key={index}>{item}</li>
})}
</ul>
ReactDOM.render(a, document.querySelector('#box'))
key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
点击切换样式
let arr1 = ['aa', 'bb', 'cc']
let curIndex = 0
function showList(arr){
return arr.map((item,index)=>{
return (
<li
key={index}
style={{color:index === curIndex?'red':''}}
onClick={()=>{
curIndex = index;
render()
}}
>
{item}
</li>
)
})
}
function render(){
ReactDOM.render(
<div>
{ showList(arr1)}
</div>,
document.querySelector('#box')
)
}
render()
函数式组件
var arr2 = ["aa","bb","cc"]
const List = props => {
console.log(props) //获取传递过来的参数
return (
<ul>
{
props.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
)
}
let obj = {
arr1:"hello world",
arr2:100
}
function App(){
return (
<div>
<h2>商品列表</h2>
<List {...obj} arr={arr2}></List>
</div>
)
}
ReactDOM.render(<App/>,document.getElementById("box"))
class组件
var goods = ["苹果","香蕉","橘子"]
class List extends React.Component{
render(){
// console.log(this.props.arr) //发现this ===> props/state/refs
let {arr} = this.props
return (
<ul>
{
arr.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
)
}
}
//定义类组件App
class App extends React.Component{
render(){ //是react生命周期里面必须要写的一个钩子
return (
<div>
<List arr={goods}/>
</div>
)
}
}
ReactDOM.render(<App/>,document.getElementById("box"))