React 构建用户界面的JavaScript库,主要用于构建UI界面。Instagram,2013年开源。
特点:
- 声明式的设计
- 高效,采用虚拟DOM来实现DOM的渲染,最大限度的减少DOM的操作。
- 灵活,跟其他库灵活搭配使用。
- JSX,俗称JS里面写HTML,JavaScript语法的扩展。
- 组件化,模块化。代码容易复用,2016年之前大型项目非常喜欢react
- 单向数据流。没有实现数据的双向绑定。数据-》视图-》事件-》数据
创建项目
1、通过script引入使用,仅用于学习调试使用
1<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> 2<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
2、通过react的脚手架,创建项目进行开发,部署
11. 安装脚手架Create React App。 2cnpm install -g create-react-app 32. 创建项目 4create-react-app 01reactapp(项目名称可以自定义)
React元素渲染
1let h1 = <h1>helloworld</h1>; 2使用JSX的写法,可以创建JS元素对象 3注意:JSX元素对象,或者组件对象,必须只有1个根元素(根节点)
案例使用:
1//实现页面时刻的显示 2 3function clock(){ 4 let time = new Date().toLocaleTimeString() 5 let element = ( 6 <div> 7 <h1>现在的时间是{time} </h1> 8 <h2>这是副标题</h2> 9 </div> 10 ) 11 let root = document.querySelector('#root'); 12 ReactDOM.render(element,root) 13} 14 15clock() 16 17setInterval(clock,1000)
函数式组件渲染
1function Clock(props){ 2 return ( 3 <div> 4 <h1>现在的时间是{props.date.toLocaleTimeString()} </h1> 5 <h2>这是函数式组件开发</h2> 6 </div> 7 ) 8} 9 10function run(){ 11 ReactDOM.render( 12 <Clock date={new Date()} />, 13 document.querySelector('#root') 14 ) 15} 16 17setInterval(run,1000)
React Jsx
优点:
- JSX执行更快,编译为JavaScript代码时进行优化
- 类型更安全,编译过程如果出错就不能编译,及时发现错误
- JSX编写模板更加简单快速。(不要跟VUE比)
注意:
- JSX必须要有根节点。
- 正常的普通HTML元素要小写。如果是大写,默认认为是组件。
JSX表达式
- 由HTML元素构成
- 中间如果需要插入变量用{}
- {}中间可以使用表达式
- {}中间表达式中可以使用JSX对象
- 属性和html内容一样都是用{}来插入内容
案例
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import './App.css' 4 5let time = new Date().toLocaleTimeString() 6let str = '当前时间是:' 7let element = ( 8 <div> 9 <h1>helloworld</h1> 10 <h2>{str+time}</h2> 11 </div> 12) 13 14console.log(element) 15 16let man = '发热'; 17let element2 = ( 18 <div> 19 <h1>今天是否隔离</h1> 20 <h2>{man=="发热"?<button>隔离</button>:"躺床上"}</h2> 21 </div> 22) 23 24//let man = '发热'; 25let element4 = ( 26 <div> 27 <span>横着躺</span> 28 <span>竖着躺</span> 29 </div> 30) 31man = '正常' 32let element3 = ( 33 <div> 34 <h1>今天是否隔离</h1> 35 <h2>{man=="发热"?<button>隔离</button>:element4}</h2> 36 </div> 37) 38 39let color = 'bgRed' 40let logo = 'https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png' 41//HTML的样式类名要写className,因为class在js当中是关键词 42let element5 = ( 43 <div className={color}> 44 <img src={logo} /> 45 红色的背景颜色 46 </div> 47 48) 49 50ReactDOM.render( 51 element5, 52 document.getElementById('root') 53 54)
JSX_style 样式
-
Class,style中,不可以存在多个class属性
-
style样式中,如果存在多个单词的属性组合,第二个单词开始,首字母大写。或者用引号引起来,否则会报错。
let exampleStyle = { background:"skyblue", borderBottom:"4px solid red", 'background-image':"url(https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png)" }
3.多个类共存的操作
1let element2 = ( 2 <div> 3 <h1 className={"abc "+classStr}>helloworld</h1> 4 </div> 5) 6 7 8let classStr2 = ['abc2','redBg2'].join(" ") 9let element3 = ( 10 <div> 11 {/* 这里写注释 */} 12 <h1 className={classStr2} style={exampleStyle}>helloworld</h1> 13 </div> 14)
4.注释
必须在括号的表达式内书写,否则报错:{/* 这里写注释 */}
React组件
函数式组件与类组件的区别和使用,函数式比较简单,一般用于静态没有交互事件内容的组件页面。类组件,一般又称为动态组件,那么一般会有交互或者数据修改的操作。
-
函数式组件
//函数式组件 function Childcom(props){ console.log(props)
1let title = <h2>我是副标题</h2> 2let weather = props.weather 3//条件判断 4let isGo = weather=='下雨' ?"不出门":"出门" 5 6return ( 7 <div> 8 <h1>函数式组件helloworld</h1> 9 {title} 10 11 <div> 12 是否出门? 13 <span>{isGo}</span> 14 </div> 15 </div> 16)}
2.类组件
1//类组件定义 2class HelloWorld extends React.Component{ 3 render(){ 4 console.log(this) 5 return ( 6 <div> 7 <h1>类组件定义HELLOWORLD</h1> 8 <h1>hello:{this.props.name}</h1> 9 <Childcom weather={this.props.weather} /> 10 </div> 11 ) 12 } 13}
3.复合组件:组件中又有其他的组件,复合组件中既可以有类组件又可以有函数组件。
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import './04style.css'; 4//函数式组件 5function Childcom(props){ 6 console.log(props) 7 8 let title = <h2>我是副标题</h2> 9 let weather = props.weather 10 //条件判断 11 let isGo = weather=='下雨' ?"不出门":"出门" 12 13 return ( 14 <div> 15 <h1>函数式组件helloworld</h1> 16 {title} 17 18 <div> 19 是否出门? 20 <span>{isGo}</span> 21 </div> 22 </div> 23 ) 24} 25 26//类组件定义 27class HelloWorld extends React.Component{ 28 render(){ 29 console.log(this) 30//返回的都是JSX对象 31 return ( 32 <div> 33 <h1>类组件定义HELLOWORLD</h1> 34 <h1>hello:{this.props.name}</h1> 35 <Childcom weather={this.props.weather} /> 36 </div> 37 ) 38 } 39 40 41} 42 43 44// ReactDOM.render( 45// <Childcom weather="出太阳" />, 46// document.querySelector('#root') 47// ) 48 49ReactDOM.render( 50 <HelloWorld name="老陈" weather="下雨" />, 51 document.querySelector('#root') 52)
React State
相当于VUE的DATA,但是使用方式跟VUE不一致。
Props
父传递给子组件数据,单向流动,不能子传递给父。
props的传值,可以是任意的类型。
Props可以设置默认值
HelloMessage.defaultProps = { name:”老陈”,msg:“helloworld” }
注意:props可以传递函数,props可以传递父元素的函数,就可以去修改父元素的state,从而达到传递数据给父元素。
父传参给子
1//在父元素中使用state去控制子元素props的从而达到父元素数据传递给子元素 2class ParentCom extends React.Component{ 3 constructor(props){ 4 super(props) 5 this.state = { 6 isActive:true 7 } 8 //绑定事件 9 this.changeShow = this.changeShow.bind(this) 10 } 11 render(){ 12 return ( 13 <div> 14 <button onClick={this.changeShow}>控制子元素显示</button> 15 <ChildCom isActive={this.state.isActive} /> 16 </div> 17 ) 18 } 19 changeShow(){ 20 this.setState({ 21 isActive:!this.state.isActive 22 }) 23 } 24} 25 26class ChildCom extends React.Component{ 27 constructor(props){ 28 super(props) 29 } 30 render(){ 31 let strClass = null; 32 if(this.props.isActive){ 33 strClass = ' active' 34 }else{ 35 strClass = "" 36 } 37 strClass = this.props.isActive?" active":""; 38 39 return ( 40 <div className={"content"+strClass}> 41 <h1>我是子元素</h1> 42 </div> 43 ) 44 } 45}
子传参给父
1class Parent extends React.Component { 2 constructor(props) { 3 super(props) 4 this.state = { 5 childData: null 6 } 7 } 8 render() { 9 return ( 10 <div> 11 <h1>子元素传递给父元素的数据:{this.state.childData}</h1> 12 {/* 将设置参数的方法通过props传给子元素 */} 13 <Child setChildData={this.setChildData}/> 14 </div> 15 ) 16 } 17 setChildData=(data)=>{ 18 this.setState({ 19 childData:data 20 }) 21 } 22} 23 24class Child extends React.Component{ 25 constructor(props){ 26 super(props) 27 this.state={ 28 msg:"helloworld" 29 } 30 } 31 render(){ 32 return( 33 <div> 34 <button onClick={this.senData}>传参给父元素</button> 35 //使用ES6,可以直接在按钮的事件中写箭头函数传参 36 <button onClick={()=>{this.props.setChildData("666")}}>传参给父元素</button> 37 //不使用ES6, 38 <button onClick={function(e){this.props.setChildData("666")}.bind(this)}>传参给父元素</button> 39 </div> 40 ) 41 } 42 //不绑定事件可以直接使用箭头函数 43 senData=()=>{ 44 从父元素传过来的props里面的方法传递参数 45 this.props.setChildData(this.state.msg) 46 } 47}
事件
特点:
1、react事件,绑定事件的命名,驼峰命名法。
2、{},传入1个函数,而不是字符串
<button onClick={this.sendData}>传递helloworld给父元素</button>
事件对象:React返回的事件对象是代理的原生的事件对象,如果想要查看事件对象的具体值,必须之间输出事件对象的属性。
注意:
原生,阻止默认行为时,可以直接返回return false;
React中,阻止默认必须e.preventDefault();
React事件传参数
1{/* 使用ES6箭头函数传递多个参数 */} 2<button onClick={(e)=>{this.parentEvent1('msg:helloworld',e)}}>提交</button> 3{/* //不使用ES6箭头函数传递多个参数的方式 */} 4<button onClick={function(e){this.parentEvent1('不使用es6,msg:helloworld',e)}.bind(this)}>提交</button>
条件渲染
1、直接通过条件运算返回要渲染的JSX对象
2、通过条件运算得出jsx对象,在将JSX对象渲染到模板中。
案例1
1function UserGreet(props){ 2 return (<h1>欢迎登陆</h1>) 3} 4 5function UserLogin(props){ 6 return (<h1>请先登录</h1>) 7} 8 9class ParentCom extends React.Component{ 10 constructor(props){ 11 super(props) 12 this.state = { 13 isLogin:true 14 } 15 } 16 render(){ 17 if(this.state.isLogin){ 18 return (<UserGreet></UserGreet>) 19 }else{ 20 return (<UserLogin></UserLogin>) 21 } 22 } 23}
案例2
1function UserGreet(props){ 2 return (<h1>欢迎登陆</h1>) 3} 4 5function UserLogin(props){ 6 return (<h1>请先登录</h1>) 7} 8 9class ParentCom extends React.Component{ 10 constructor(props){ 11 super(props) 12 this.state = { 13 isLogin:false 14 } 15 } 16 render(){ 17 let element = null; 18 if(this.state.isLogin){ 19 element = <UserGreet></UserGreet>; 20 }else{ 21 element = (<UserLogin></UserLogin>); 22 } 23 24 25 26 return ( 27 <div> 28 <h1>这是头部</h1> 29 {element} 30 <h1>这是三元运算符的操作</h1> 31 {this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>} 32 <h1>这是尾部</h1> 33 </div> 34 ) 35 } 36}
列表渲染
将列表内容拼装成数组放置到模板中。将数据拼装成数组的JSX对象。
使用数组的map方法,对每一项数据按照JSX的形式进行加工,最终得到1个每一项都是JSX对象的数组,在将数组渲染到模板中。
Key值需要放置到每一项中。
案例1
1class Welcome extends React.Component{ 2 constructor(props){ 3 super(props) 4 this.state = { 5 list:[ 6 { 7 title:"第一节 React事件", 8 content:"事件内容" 9 }, 10 { 11 title:"第二节 React数据传递", 12 content:"数据传递内容", 13 }, 14 { 15 title:"第三节 条件渲染", 16 content:"条件渲染内容", 17 } 18 ] 19 } 20 } 21 22 render(){ 23 let listArr = []; 24 for(let i=0;i<this.state.list.length;i++){ 25 let item = ( 26 <li> 27 <h3>{this.state.list[i].title}</h3> 28 <p>{this.state.list[i].content}</p> 29 </li> 30 ) 31 listArr.push(item) 32 } 33 return ( 34 <div> 35 <h1> 36 今天课程内容 37 </h1> 38 39 <ul> 40 {listArr} 41 <li> 42 <h3>这是标题</h3> 43 <p>内容</p> 44 </li> 45 </ul> 46 47 </div> 48 ) 49 } 50}
案例2
1function ListItem(props){ 2 return ( 3 <li> 4 <h3>{props.index+1}:listItem:{props.data.title}</h3> 5 <p>{props.data.content}</p> 6 </li> 7 ) 8} 9 10class ListItem2 extends React.Component{ 11 constructor(props){ 12 super(props) 13 } 14 render(){ 15 return ( 16 <li onClick={(event)=>{this.clickEvent( 17 this.props.index, 18 this.props.data.title, 19 event 20 )}}> 21 <h3>{this.props.index+1}:listItem:{this.props.data.title}</h3> 22 <p>{this.props.data.content}</p> 23 </li> 24 ) 25 } 26 clickEvent=(index,title,event)=>{ 27 alert((index+1)+"-"+title) 28 } 29} 30 31 32class Welcome extends React.Component{ 33 constructor(props){ 34 super(props) 35 this.state = { 36 list:[ 37 { 38 title:"第一节 React事件", 39 content:"事件内容" 40 }, 41 { 42 title:"第二节 React数据传递", 43 content:"数据传递内容", 44 }, 45 { 46 title:"第三节 条件渲染", 47 content:"条件渲染内容", 48 } 49 ] 50 } 51 } 52 53 render(){ 54 let listArr = this.state.list.map((item,index)=>{ 55 return ( 56 <ListItem2 key={index} data={item} index={index}></ListItem2> 57 58 ) 59 }) 60 61 return ( 62 <div> 63 <h1> 64 今天课程内容 65 </h1> 66 67 <ul> 68 {listArr} 69 <li> 70 <h3>这是标题</h3> 71 <p>内容</p> 72 </li> 73 </ul> 74 75 <h1>复杂没有用组件完成列表</h1> 76 <ul> 77 { 78 this.state.list.map((item,index)=>{ 79 return ( 80 <li key={index} onClick={(event)=>{this.clickFn(index,item.title,event)}}> 81 <h3>{index+1}-复杂-{item.title}</h3> 82 <p>{item.content}</p> 83 </li> 84 ) 85 }) 86 } 87 </ul> 88 89 </div> 90 ) 91 } 92 93 clickFn=(index,title,event)=>{ 94 alert((index+1)+"-clickFn-"+title) 95 } 96}
生命周期
生命周期即是组件从实例化到渲染到最终从页面中销毁,整个过程就是生命周期,在这生命周期中,我们有许多可以调用的事件,也俗称为钩子函数
生命周期的3个状态:
Mounting:将组件插入到DOM中
Updating:将数据更新到DOM中
Unmounting:将组件移除DOM中
生命周期中的钩子函数(方法,事件)
CompontWillMount :组件将要渲染,AJAX,添加动画前的类
CompontDidMount:组件渲染完毕,添加动画
compontWillReceiveProps:组件将要接受props数据,查看接收props的数据什么
ShouldComponentUpdate:组件接收到新的state或者props,判断是否更新。返回布尔值
CompontWillUpdate:组件将要更新
ComponentDidUpdate:组件已经更新
ComponentwillUnmount:组件将要卸载
React插槽
组建中写入内容,这些内容可以被识别和控制。React需要自己开发支持插槽功能。
原理:
组件中写入的HTML,可以传入到props中。
组件中的HTML内容直接全部插入
组件中的HTML内容直接全部插入
1class ParentCom extends React.Component{ 2 3 render(){ 4 console.log(this.props) 5 return ( 6 <div> 7 <h1>组件插槽</h1> 8 {this.props.children} 9 </div> 10 ) 11 } 12}
组件中根据HTML内容的不同,插入的位置不同。
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3 4class ParentCom extends React.Component{ 5 6 render(){ 7 console.log(this.props) 8 return ( 9 <div> 10 <h1>组件插槽</h1> 11 {this.props.children} 12 <ChildCom> 13 <h1 data-position="header">这是放置到头部的内容</h1> 14 <h1 data-position="main">这是放置到主要的内容</h1> 15 <h1 data-position="footer">这是放置到尾部的内容</h1> 16 </ChildCom> 17 </div> 18 ) 19 } 20} 21 22class ChildCom extends React.Component{ 23 render(){ 24 let headerCom,mainCom,footerCom; 25 this.props.children.forEach((item,index)=>{ 26 if(item.props['data-position']==='header'){ 27 headerCom = item 28 }else if(item.props['data-position']==='main'){ 29 mainCom = item 30 }else{ 31 footerCom = item 32 } 33 }) 34 return ( 35 <div> 36 <div className="header"> 37 {headerCom} 38 </div> 39 <div className="main"> 40 {mainCom} 41 </div> 42 <div className="footer"> 43 {footerCom} 44 </div> 45 </div> 46 ) 47 } 48} 49 50class RootCom extends React.Component{ 51 constructor(props){ 52 super(props) 53 //console.log(props) 54 this.state = { 55 arr:[1,2,3] 56 } 57 } 58 render(){ 59 return ( 60 <ParentCom> 61 <h2 data-name="a" data-index={this.state.arr[0]}>子组件1</h2> 62 <h2 data-name="b" data-index={this.state.arr[1]}>子组件2</h2> 63 <h2 data-name="c" data-index={this.state.arr[2]}>子组件3</h2> 64 </ParentCom> 65 ) 66 } 67} 68 69ReactDOM.render( 70 <RootCom></RootCom> 71 , 72 document.querySelector("#root") 73)
React 路由
根据不同的路径,显示不同的组件(内容);React使用的库react-router-dom;
安装
Cnpm install react-router-dom --save
ReactRouter三大组件:
Router:所有路由组件的根组件(底层组件),包裹路由规则的最外层容器。
属性:basename->设置跟此路由根路径,router可以在1个组件中写多个。
Route:路由规则匹配组件,显示当前规则对应的组件
Link:路由跳转的组件
注意:如果要精确匹配,那么可以在route上设置exact属性。
Router使用案例
1import React from 'react'; 2//hash模式 3//import {HashRouter as Router,Link,Route} from 'react-router-dom' 4 5//history模式/后端匹配使用 6import {BrowserRouter as Router,Link,Route} from 'react-router-dom' 7 8function Home(){ 9 return ( 10 <div> 11 <h1>admini首页</h1> 12 </div> 13 ) 14} 15 16function Me(){ 17 return ( 18 <div> 19 <h1>admin个人中心</h1> 20 </div> 21 ) 22} 23 24function Product(){ 25 return ( 26 <div> 27 <h1>admin产品页面</h1> 28 </div> 29 ) 30} 31 32class App extends React.Component{ 33 34 render(){ 35 return ( 36 <div id="app"> 37 {/* <div>所有页面普通内容</div> */} 38 <Router> 39 <Route path="/" exact component={()=>(<div>首页</div>)}></Route> 40 <Route path="/me" component={()=>(<div>me</div>)}></Route> 41 <Route path="/product" component={()=>(<div>product</div>)}></Route> 42 </Router> 43 44 <Router> 45 {/* <div className="nav"> 46 <Link to="/">Home</Link> 47 <Link to="/product">Product</Link> 48 <Link to="/me">个人中心</Link> 49 </div> */} 50 <Route path="/admin/" exact component={Home}></Route> 51 <Route path="/admin/product" component={Product}></Route> 52 <Route path="/admin/me" exact component={Me}></Route> 53 </Router> 54 </div> 55 ) 56 } 57} 58 59export default App
Link组件可以设置to属性来进行页面的跳转,to属性可以直接写路径的字符串,也可以通过1个对象,进行路径的设置,如
1render(){ 2 let meObj = { 3 pathname:"/me",//跳转的路径 4 search:"?username=admin",//get请求参数 5 hash:"#abc",//设置的HASH值 6 state:{msg:'helloworld'}//传入组件的数据 7 }; 8 return ( 9 <div id="app"> 10 11 12 <Router> 13 <div className="nav"> 14 <Link to="/">Home</Link> 15 <Link to="/product">Product</Link> 16 <Link to={ meObj }>个人中心</Link> 17 </div> 18 <Route path="/" exact component={Home}></Route> 19 <Route path="/product" component={Product}></Route> 20 <Route path="/me" exact component={Me}></Route> 21 </Router> 22 </div> 23 ) 24 }
Link的replace属性:点击链接后,将新地址替换成历史访问记录的原地址。
动态路由实现:
1import React from 'react'; 2//hash模式 3//import {HashRouter as Router,Link,Route} from 'react-router-dom' 4 5//history模式/后端匹配使用 6import {BrowserRouter as Router,Link,Route} from 'react-router-dom' 7 8function Home(){ 9 return ( 10 <div> 11 <h1>admini首页</h1> 12 </div> 13 ) 14} 15 16function Me(props){ 17 console.log(props) 18 return ( 19 <div> 20 <h1>admin个人中心</h1> 21 </div> 22 ) 23} 24 25function Product(){ 26 return ( 27 <div> 28 <h1>admin产品页面</h1> 29 </div> 30 ) 31} 32 33function News(props){ 34 console.log(props) 35 return ( 36 <div> 37 新闻页,新闻id:{props.match.params.id} 38 </div> 39 ) 40} 41 42class App extends React.Component{ 43 44 render(){ 45 let meObj = { 46 pathname:"/me",//跳转的路径 47 search:"?username=admin",//get请求参数 48 hash:"#abc",//设置的HASH值 49 state:{msg:'helloworld'}//传入组件的数据 50 }; 51 return ( 52 <div id="app"> 53 54 55 <Router> 56 <div className="nav"> 57 <Link to="/">Home</Link> 58 <Link to="/product">Product</Link> 59 <Link to={ meObj } replace>个人中心</Link> 60 <Link to="/news/4568789">新闻页</Link> 61 </div> 62 <Route path="/" exact component={Home}></Route> 63 <Route path="/product" component={Product}></Route> 64 <Route path="/me" exact component={Me}></Route> 65 <Route path="/news/:id" component={News}></Route> 66 </Router> 67 </div> 68 ) 69 } 70} 71 72export default App
重定向组件
如果访问某个组件时,如果有重定向组件,那么就会修改页面路径,使得页面内容显示为所定向路径的内容
用例:
1function LoginInfo(props){ 2 //props.loginState = 'success'; 3 //props.loginState = "fail" 4 console.log(props) 5 if(props.location.state.loginState === 'success'){ 6 return <Redirect to="/admin"></Redirect> 7 }else{ 8 return <Redirect to="/login"></Redirect> 9 } 10}
Switch组件
让switch组件内容的route只匹配1个,只要匹配到了,剩余的路由规则将不再匹配
1class App extends React.Component{ 2 render(){ 3 return ( 4 <div> 5 <Router> 6 <Switch> 7 <Route path="/" exact component={()=>(<h1>首页</h1>)}></Route> 8 <Route path="/form" exact component={FormCom}></Route> 9 <Route path="/login" exact component={()=>(<h1>登录页</h1>)}></Route> 10 <Route path="/logininfo" exact component={LoginInfo}></Route> 11 <Route path="/admin" exact component={()=>(<h1>admin页,登录成功</h1>)}></Route> 12 <Route path="/abc" exact component={()=>(<h1>abc1页,登录成功</h1>)}></Route> 13 <Route path="/abc" exact component={()=>(<h1>abc2页,登录成功</h1>)}></Route> 14 </Switch> 15 </Router> 16 </div> 17 ) 18 } 19}
Redux
解决React数据管理(状态管理),用于中大型,数据比较庞大,组件之间数据交互多的情况下使用。如果你不知道是否需要使用Redux,那么你就不需要用它!
* 解决组件的数据通信。
* 解决数据和交互较多的应用
Redux只是一种状态管理的解决方案!
Store:数据仓库,保存数据的地方。
State:state是1个对象,数据仓库里的所有数据都放到1个state里。
Action:1个动作,触发数据改变的方法。
Dispatch:将动作触发成方法
Reducer:是1个函数,通过获取动作,改变数据,生成1个新state。从而改变页面
安装
Cnpm install redux --save
初始化数据
1//创建仓库 2const store = createStore(reducer) 3//用于通过动作,创建新的state 4//reduce有2个作用,1初始化数据,第二个就是通过获取动作,改变数据 5const reducer = function(state={num:0},action){ 6 console.log(action) 7 switch(action.type){ 8 case "add": 9 state.num++; 10 break; 11 case 'decrement': 12 state.num--; 13 break; 14 default: 15 break; 16 } 17 return {...state}//相当于对象的COPY 18}
获取数据
let state = store.getState()
修改数据(通过动作修改数据)
1//通过仓库的方法dispatch进行修改数据 2store.dispatch({type:"add",content:{id:1,msg:"helloworld"}})
修改视图(监听数据的变化,重新渲染内容)
1store.subscribe(()=>{ 2 ReactDOM.render(<Counter></Counter>,document.querySelector("#root")) 3})
完整案例
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import {createStore} from 'redux' 4 5//用于通过动作,创建新的state 6const reducer = function(state={num:0},action){ 7 console.log(action) 8 switch(action.type){ 9 case "add": 10 state.num++; 11 break; 12 case 'decrement': 13 state.num--; 14 break; 15 default: 16 break; 17 } 18 return {...state}//相当于对象的COPY 19} 20 21//创建仓库 22const store = createStore(reducer) 23console.log(store) 24 25 26function add(){ 27 //通过仓库的方法dispatch进行修改数据 28 store.dispatch({type:"add",content:{id:1,msg:"helloworld"}}) 29 console.log(store.getState()) 30} 31function decrement(){ 32 //通过仓库的方法dispatch进行修改数据 33 store.dispatch({type:"decrement"}) 34 console.log(store.getState()) 35} 36//函数式计数器 37const Counter = function(props){ 38 //console.log(store.getState()) 39 let state = store.getState() 40 return ( 41 <div> 42 <h1>计数数量:{state.num}</h1> 43 44 <button onClick={add}>计数+1</button> 45 <button onClick={decrement}>计数-1</button> 46 </div> 47 ) 48 49} 50 51ReactDOM.render(<Counter></Counter>,document.querySelector("#root")) 52store.subscribe(()=>{ 53 ReactDOM.render(<Counter></Counter>,document.querySelector("#root")) 54})
React-redux
安装
cnpm install react-redux --save
概念:
Provider组件:自动的将store里的state和组件进行关联。
MapStatetoProps:这个函数用于将store的state映射到组件的里props
mapdispatchToProps:将store中的dispatch映射到组件的props里,实现了方法的共享。
Connect方法:将组件和数据(方法)进行连接
使用:
初始化数据,实例化store
1function reducer(state={num:0},action){ 2 switch(action.type){ 3 case "add": 4 state.num++; 5 break; 6 default: 7 break; 8 } 9 return {...state} 10} 11 12const store = createStore(reducer)
数据的获取,数据的修改
要state映射到到组件的props中,将修改数据的方法映射到组件的props中
完整案例
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import {createStore} from 'redux'; 4import {connect, Provider} from 'react-redux' 5 6class Counter extends React.Component{ 7 8 render(){ 9 console.log(this.props) 10 //计数,通过stroe的state传给props,直接通过props就可以将state的数据获取 11 const value = this.props.value; 12 //将修改数据的事件或者方法传入到props 13 const onAddClick = this.props.onAddClick; 14 //等同于vuex的mapMutation mapState 15 return ( 16 <div> 17 <h1>计数的数量:{value}</h1> 18 <button onClick={onAddClick}>数字+1</button> 19 <button onClick={this.props.onAddClick5}>数字+5</button> 20 </div> 21 ) 22 23 24 } 25} 26 27 28 29let ActionFnObj={ 30 add:function(state,action){ 31 state.num++ 32 return state 33 }, 34 addNum:function(state,action){ 35 36 state.num = state.num + action.num; 37 return state 38 } 39} 40function reducer(state={num:0},action){ 41 if(action.type.indexOf('redux')===-1){ 42 state = ActionFnObj[action.type](state,action) 43 return {...state} 44 }else{ 45 return state; 46 } 47 48 49} 50 51const store = createStore(reducer) 52 53//将state映射到props函数 54function mapStateToProps(state){ 55 return { 56 value:state.num 57 58 } 59} 60 61const addAction = { 62 type:'add' 63} 64//将修改state数据的方法,映射到props,默认会传入store里的dispach方法 65function mapDispatchToProps(dispatch){ 66 return { 67 onAddClick:()=>{dispatch(addAction)}, 68 onAddClick5:()=>{dispatch({type:"addNum",num:5})} 69 } 70} 71 72//将上面的这2个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件。 73const App = connect( 74 mapStateToProps, 75 mapDispatchToProps 76)(Counter) 77 78ReactDOM.render( 79 <Provider store={store}> 80 <App></App> 81 </Provider>, 82 document.querySelector("#root") 83)
Ant 蚂蚁框架
npm install antd-mobile --save
按需要导入(自动导入用到的css样式):
-
安装插件
npm install babel-plugin-import --save
2.配置
npm run eject
3.Packjson文件
1"babel": { 2 "presets": [ 3 "react-app" 4 ], 5 "plugins": [ 6 ["import", { "libraryName": "antd-mobile", "style": "css" }] 7 ] 8 }
其余参考官网