一.react 生态圈
- JSX 扩展的JS,react强依赖
- Flux(相当于VUEX,用的少)
- Redux(相当于VUEX,经常用)
- react-Native 开发移动端
- react-Server 在服务端渲染
二.script 引入react开发
1.公共引入文件
<script src="browser.js" charset="utf-8"></script>
<script src="react.development.js" charset="utf-8"></script>
<script src="react-dom.development.js" charset="utf-8"></script>
2.简单的渲染页面
<body>
<div id="div1"></div>
</body>
<script type="text/babel">
let root=document.getElementById('div1');
ReactDOM.render(
<div>
<label htmlFor="user">用户名:</label>
<input id="user" type="text" />
</div>,
root
);
</script>
3.组件
<body><div id="div1"></div></body>
<script type="text/babel">
class Cmp1 extends React.Component{
constructor(...args){
super(...args);
this.name='blue';
this.age=18;
}
fn(){
return 'aaa';
}
//render(){
//let arr=[];
//for(let i=0;i<6;i++){
//arr.push(
//<li key={i}>{i}</li>
//);
//}
//return (
// <div>
// 姓名:{this.name}<br/>
// 年龄:{this.age+5}<br/>
// <ul> {arr} </ul>
// </div>
//);
// }
render(){
let datas=[
{name: 'blue', age: 18},
{name: 'zhangsan', age: 25},
{name: 'lisi', age: 28},
];
return (
<div>
<ul>
{datas.map((data,index)=>(
<li key={index}>
姓名:{data.name}<br/>
年龄:{data.age}
</li>
))}
</ul>
</div>
);
}
}
let root=document.getElementById('div1');
ReactDOM.render(
<div>
<label htmlFor="user">用户名:</label>
<input id="user" type="text" />
<Cmp1></Cmp1>
</div>,
root
);
</script>
4.父子组件及传参
<body><div id="div1"></div></body>
<script type="text/babel">
//父组件
class Parent extends React.Component{
constructor(...args){
super(...args);
}
render(){
return (
<ul>
{this.props.arr.map((str,index)=><Child txt={str} key={index}/>)}
</ul>
);
}
}
//子组件
class Child extends React.Component{
constructor(...args){
super(...args);
}
render(){
return (
<li>
{this.props.txt}
</li>
);
}
}
let root=document.getElementById('div1');
ReactDOM.render(
<div>
<label htmlFor="user">用户名:</label>
<input id="user" type="text" />
//渲染
<Parent arr={['dfsdf', 'sdfsdf', 'werwer']} />
</div>,
root
);
</script>
5.传参误区
注意:1.传入的参数 this.props获取,是只读的不能够修改。2.this.state是组件内部的状态可以修改
class Cmp1 extends React.Component{
constructor(...args){
super(...args);
this.state={a: 0};
}
fn(){
//此参数状态为组件传入值this.props.a 是只读状态不能修改 所以报错
this.props.a++;
//此为组件内部状态可以修改 setState修改后并重新渲染组件
this.setState({
a: this.state.a+1
});
}
render(){
return (
<div>
<input type="button" value="+1" onClick={this.fn.bind(this)} />
1.不变:{this.props.a}
2.会变:{this.state.a}
</div>
);
}
}
let root=document.getElementById('div1');
ReactDOM.render(
<div>
<Cmp1 a={0} />
</div>,
root
);
6.组件通信(父组件获取子组件)
//父组件
class Parent extends React.Component{
constructor(...args){
super(...args);
}
fn(){
//和vue类似 子组件定义ref来获取子组件的方法或属性
this.refs['child1'].add(7);
}
render(){
return (
<div>
<input type="button" value="+1" onClick={this.fn.bind(this)} />
<Child ref="child1"/>
</div>
);
}
}
//子组件
class Child extends React.Component{
constructor(...args){
super(...args);
this.state={a: 0};
}
add(n){
this.setState({
a: this.state.a+n
});
}
render(){
return ( <div>{this.state.a}</div> );
}
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
<div><Parent a={0} /></div>,
root
);
7.组件通信(子组件获取父组件)
//父组件
class Parent extends React.Component{
constructor(...args){
super(...args);
this.state={a: 0};
}
add(n){
//修改父组件内部状态
this.setState({
a: this.state.a+n
});
}
render(){
return (
<div>
{this.state.a}
<Child parent={this}/>
</div>
);
}
}
//子组件
class Child extends React.Component{
constructor(...args){
super(...args);
}
render(){
return (
<div>
<input type="button" value="+1" onClick={function (){
//1.在父组件件里的子组件上定义属性parent并把this传入
//2.通过this.props.parent来获取父组件的属性或方法
this.props.parent.add(11)
}.bind(this)} />
</div>
);
}
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
<div><Parent a={0} /></div>,
root
);
8.组件的生命周期
子组件渲染完成后,父组件才算渲染完成
//父组件
class Parent extends React.Component{
constructor(...args){
super(...args);
this.state={a: 0};
}
componentDidMount(){
console.log('父组件已经挂载');
}
componentDidUpdate(){
console.log('父组件已经更新');
}
componentWillUnmount(){
console.log("组件销毁时执行")
}
fn(){
this.setState({
a: this.state.a+3
});
}
render(){
return (
<div>
<input type="button" value="+1" onClick={this.fn.bind(this)} />
<Child a={this.state.a}/>
</div>
);
}
}
//子组件
class Child extends React.Component{
constructor(...args){
super(...args);
}
componentDidMount(){
console.log('子组件已经挂载');
}
componentDidUpdate(){
console.log('子组件已经更新');
}
render(){
return (
<div>
{this.props.a}
</div>
);
}
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
<div><Parent /></div>,
root
);
9.redux - 集中状态管理
- provider
1.整个redux最外层集中的作用域。2.包在最外层
- connect
状态的映射
- reducer
状态对象 多个reducer管不同对象
4.action状态的更新 (字符串或对象等)
安装:
要安装redux和react-redun
1.yarn add redux
2.yarn add react-redun
使用:
1.在index.js中
//在最外层文件(eg:index.js)中引入
import { createStore } from "redux"
import { Provider } from "react-redux"
//1.创建存储
function reducer1(state={name:"blue",age:18},action){
switch (action.type) {
case "set_name":
//state.name = action.name 这样写改不了
//修改方式必须是新的对象 用下面的name覆盖上面的name
return {
...state,
name:action.name
}
case "add_age":
return {
...state,
age:state.age + action.age
}
default:
return state
}
}
//2.创建存储对象
const store = createStore(reducer1)
ReactDOM.render(
<React.StrictMode>
//3.用Provider包裹整个App组件 在App里所有组件都可使用store
<Provider store={store}>
<App a={15} b={10} name="张三"/>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
2.在App.js中
import React from "react";
import { connect } from 'react-redux';
class Cmp1 extends React.Component {
fn (){
this.props.setName("张三")
}
addFn (){
this.props.addAge(6)
}
render (){
return (
<div>
<input type="button" value="改名" onClick={this.fn.bind(this)}/>
{this.props.name}
<input type="button" value="加6" onClick={this.addFn.bind(this)}/>
{this.props.age}
</div>
)
}
}
//connect连接全局的属性
//connect两个参数 第一个是合并state和props 第二个是个json对象 action修改
export default connect(function(state,props){
//state为全局的store数据,
//props为本组件传入的数据
//console.log(state,props)
return {
...state,
...props
}
},{
setName (newName){
//修改传入的name
return {
type:'set_name',
name:newName
}
},
addAge (n){
//修改传入的age
return {
type:'add_age',
age:n
}
}
})(Cmp1)