React 入门及学习笔记

原创
05/08 23:43
阅读数 93

React 构建用户界面的JavaScript库,主要用于构建UI界面。Instagram2013年开源。

特点:

  1. 声明式的设计
  2. 高效,采用虚拟DOM来实现DOM的渲染,最大限度的减少DOM的操作。
  3. 灵活,跟其他库灵活搭配使用。
  4. JSX,俗称JS里面写HTMLJavaScript语法的扩展。
  5. 组件化,模块化。代码容易复用,2016年之前大型项目非常喜欢react
  6. 单向数据流。没有实现数据的双向绑定。数据-》视图-》事件-》数据

创建项目

1、通过script引入使用,仅用于学习调试使用

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

2、通过react的脚手架,创建项目进行开发,部署

1.	安装脚手架Create React App。
cnpm install -g create-react-app
2.	创建项目
create-react-app 01reactapp(项目名称可以自定义)

React元素渲染

let h1 = <h1>helloworld</h1>;
使用JSX的写法,可以创建JS元素对象
注意:JSX元素对象,或者组件对象,必须只有1个根元素(根节点)

案例使用:

//实现页面时刻的显示

function clock(){
    let time = new Date().toLocaleTimeString()
    let element = (
        <div>
            <h1>现在的时间是{time} </h1>
            <h2>这是副标题</h2>
        </div>
    )
    let root = document.querySelector('#root');
    ReactDOM.render(element,root)
}

clock()

setInterval(clock,1000)

函数式组件渲染

function Clock(props){
    return (
                <div>
                    <h1>现在的时间是{props.date.toLocaleTimeString()} </h1>
                    <h2>这是函数式组件开发</h2>
                </div>
    )
}

function run(){
    ReactDOM.render(
        <Clock date={new Date()} />,
        document.querySelector('#root')
    )
}

setInterval(run,1000)

React Jsx

优点:

  1. JSX执行更快,编译为JavaScript代码时进行优化
  2. 类型更安全,编译过程如果出错就不能编译,及时发现错误
  3. JSX编写模板更加简单快速。(不要跟VUE比)

注意:

  1. JSX必须要有根节点。
  2. 正常的普通HTML元素要小写。如果是大写,默认认为是组件。

JSX表达式

  1. HTML元素构成
  2. 中间如果需要插入变量用{}
  3. {}中间可以使用表达式
  4. {}中间表达式中可以使用JSX对象
  5. 属性和html内容一样都是用{}来插入内容

案例

import React from 'react';
import ReactDOM from 'react-dom';
import './App.css'

let time = new Date().toLocaleTimeString()
let str = '当前时间是:'
let element = (
    <div>
        <h1>helloworld</h1>
        <h2>{str+time}</h2>
    </div>
)

console.log(element)

let man = '发热';
let element2 = (
    <div>
        <h1>今天是否隔离</h1>
        <h2>{man=="发热"?<button>隔离</button>:"躺床上"}</h2>
    </div>
)

//let man = '发热';
let element4 = (
    <div>
        <span>横着躺</span>
        <span>竖着躺</span>
    </div>
)
man = '正常'
let element3 = (
    <div>
        <h1>今天是否隔离</h1>
        <h2>{man=="发热"?<button>隔离</button>:element4}</h2>
    </div>
)

let color = 'bgRed'
let logo = 'https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png'
//HTML的样式类名要写className,因为class在js当中是关键词
let element5 = (
    <div className={color}>
        <img src={logo} />
        红色的背景颜色
    </div>

)

ReactDOM.render(
    element5,
    document.getElementById('root')

)

JSX_style 样式

  1. Classstyle中,不可以存在多个class属性
  2. style样式中,如果存在多个单词的属性组合,第二个单词开始,首字母大写。或者用引号引起来,否则会报错。
let exampleStyle = {
    background:"skyblue",
    borderBottom:"4px solid red",
    'background-image':"url(https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png)"
}

3.多个类共存的操作

let element2 = (
    <div>
        <h1 className={"abc "+classStr}>helloworld</h1>
    </div>
)


let classStr2 = ['abc2','redBg2'].join(" ")
let element3 = (
    <div>
        {/* 这里写注释 */}
        <h1 className={classStr2} style={exampleStyle}>helloworld</h1>
    </div>
)

4.注释

必须在括号的表达式内书写,否则报错:{/* 这里写注释 */}

React组件

函数式组件与类组件的区别和使用,函数式比较简单,一般用于静态没有交互事件内容的组件页面。类组件,一般又称为动态组件,那么一般会有交互或者数据修改的操作。

  1. 函数式组件
//函数式组件
function Childcom(props){
    console.log(props)

    let title = <h2>我是副标题</h2>
    let weather = props.weather
    //条件判断 
    let isGo = weather=='下雨' ?"不出门":"出门"

    return (
        <div>
            <h1>函数式组件helloworld</h1>
            {title}

            <div>
                是否出门?
                <span>{isGo}</span>
            </div>
        </div>
    )
}

2.类组件

//类组件定义
class HelloWorld extends React.Component{
    render(){
        console.log(this)
        return (
            <div>
                <h1>类组件定义HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }
}

3.复合组件:组件中又有其他的组件,复合组件中既可以有类组件又可以有函数组件。

import React from 'react';
import ReactDOM from 'react-dom';
import './04style.css';
//函数式组件
function Childcom(props){
    console.log(props)

    let title = <h2>我是副标题</h2>
    let weather = props.weather
    //条件判断 
    let isGo = weather=='下雨' ?"不出门":"出门"

    return (
        <div>
            <h1>函数式组件helloworld</h1>
            {title}

            <div>
                是否出门?
                <span>{isGo}</span>
            </div>
        </div>
    )
}

//类组件定义
class HelloWorld extends React.Component{
    render(){
        console.log(this)
//返回的都是JSX对象
        return (
            <div>
                <h1>类组件定义HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }


}


// ReactDOM.render(
//     <Childcom weather="出太阳" />,
//     document.querySelector('#root')
// )

ReactDOM.render(
    <HelloWorld name="老陈" weather="下雨" />,
    document.querySelector('#root')
)

React State

相当于VUEDATA,但是使用方式跟VUE不一致。

Props

父传递给子组件数据,单向流动,不能子传递给父。

props的传值,可以是任意的类型。

Props可以设置默认值

HelloMessage.defaultProps = {  name:”老陈msg:“helloworld  }

注意:props可以传递函数,props可以传递父元素的函数,就可以去修改父元素的state,从而达到传递数据给父元素。

父传参给子

//在父元素中使用state去控制子元素props的从而达到父元素数据传递给子元素
class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isActive:true
        }
        //绑定事件
        this.changeShow = this.changeShow.bind(this)
    }
    render(){
        return (
            <div>
                <button onClick={this.changeShow}>控制子元素显示</button>
                <ChildCom isActive={this.state.isActive} />
            </div>
        )
    }
    changeShow(){
        this.setState({
            isActive:!this.state.isActive
        })
    }
}

class ChildCom extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        let strClass = null;
        if(this.props.isActive){
            strClass = ' active'
        }else{
            strClass = ""
        }
        strClass = this.props.isActive?" active":"";

        return (
            <div className={"content"+strClass}>
                <h1>我是子元素</h1>
            </div>
        )
    }
}

子传参给父

class Parent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            childData: null
        }
    }
    render() {
        return ( 
          <div>
            <h1>子元素传递给父元素的数据:{this.state.childData}</h1>
            {/* 将设置参数的方法通过props传给子元素 */}
            <Child setChildData={this.setChildData}/>
          </div>
        )
    }
    setChildData=(data)=>{
      this.setState({
        childData:data
      })
    }
}

class Child extends React.Component{
  constructor(props){
    super(props)
    this.state={
      msg:"helloworld"
    }
  }
  render(){
    return(
      <div>
        <button onClick={this.senData}>传参给父元素</button>
       //使用ES6,可以直接在按钮的事件中写箭头函数传参
        <button onClick={()=>{this.props.setChildData("666")}}>传参给父元素</button>
        //不使用ES6,
        <button onClick={function(e){this.props.setChildData("666")}.bind(this)}>传参给父元素</button>
      </div>
    )
  }
  //不绑定事件可以直接使用箭头函数
  senData=()=>{
    从父元素传过来的props里面的方法传递参数
    this.props.setChildData(this.state.msg)
  }
}

事件

特点:

1、react事件,绑定事件的命名,驼峰命名法。

2、{},传入1个函数,而不是字符串

<button onClick={this.sendData}>传递helloworld给父元素</button>

事件对象:React返回的事件对象是代理的原生的事件对象,如果想要查看事件对象的具体值,必须之间输出事件对象的属性。

注意:

原生,阻止默认行为时,可以直接返回return false

React中,阻止默认必须e.preventDefault();

React事件传参数

{/* 使用ES6箭头函数传递多个参数 */}
<button  onClick={(e)=>{this.parentEvent1('msg:helloworld',e)}}>提交</button>
{/* //不使用ES6箭头函数传递多个参数的方式 */}
<button  onClick={function(e){this.parentEvent1('不使用es6,msg:helloworld',e)}.bind(this)}>提交</button>

条件渲染

1、直接通过条件运算返回要渲染的JSX对象

2、通过条件运算得出jsx对象,在将JSX对象渲染到模板中。

案例1

function UserGreet(props){
    return (<h1>欢迎登陆</h1>)
}

function UserLogin(props){
    return (<h1>请先登录</h1>)
}

class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:true
        }
    }
    render(){
        if(this.state.isLogin){
            return (<UserGreet></UserGreet>)
        }else{
            return (<UserLogin></UserLogin>)
        }
    }
}

案例2

function UserGreet(props){
    return (<h1>欢迎登陆</h1>)
}

function UserLogin(props){
    return (<h1>请先登录</h1>)
}

class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:false
        }
    }
    render(){
        let element = null;
        if(this.state.isLogin){
            element = <UserGreet></UserGreet>;
        }else{
            element = (<UserLogin></UserLogin>);
        }

        

        return (
            <div>
                <h1>这是头部</h1>
                {element}
                <h1>这是三元运算符的操作</h1>
                {this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>}
                <h1>这是尾部</h1>
            </div>
        )
    }
}

列表渲染

将列表内容拼装成数组放置到模板中。将数据拼装成数组的JSX对象。

使用数组的map方法,对每一项数据按照JSX的形式进行加工,最终得到1个每一项都是JSX对象的数组,在将数组渲染到模板中。

Key值需要放置到每一项中。

案例1

class Welcome extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            list:[
                {
                    title:"第一节 React事件",
                    content:"事件内容"
                },
                {
                    title:"第二节 React数据传递",
                    content:"数据传递内容",
                },
                {
                    title:"第三节 条件渲染",
                    content:"条件渲染内容",
                }
            ]
        }
    }

    render(){
        let listArr = [];
        for(let i=0;i<this.state.list.length;i++){
            let item = (
                <li>
                    <h3>{this.state.list[i].title}</h3>
                    <p>{this.state.list[i].content}</p>
                </li>
            )
            listArr.push(item)
        }
        return (
            <div>
                <h1>
                    今天课程内容
                </h1>

                <ul>
                    {listArr}
                    <li>
                        <h3>这是标题</h3>
                        <p>内容</p>
                    </li>
                </ul>

            </div>
        )
    }
}

案例2

function ListItem(props){
    return (
        <li>
            <h3>{props.index+1}:listItem:{props.data.title}</h3>
            <p>{props.data.content}</p>
        </li>
    )
}

class ListItem2 extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        return (
            <li onClick={(event)=>{this.clickEvent(
                this.props.index,
                this.props.data.title,
                event
                )}}>
                <h3>{this.props.index+1}:listItem:{this.props.data.title}</h3>
                <p>{this.props.data.content}</p>
            </li>
        )
    }
    clickEvent=(index,title,event)=>{
        alert((index+1)+"-"+title)
    }
}


class Welcome extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            list:[
                {
                    title:"第一节 React事件",
                    content:"事件内容"
                },
                {
                    title:"第二节 React数据传递",
                    content:"数据传递内容",
                },
                {
                    title:"第三节 条件渲染",
                    content:"条件渲染内容",
                }
            ]
        }
    }

    render(){
        let listArr = this.state.list.map((item,index)=>{
            return (
                <ListItem2 key={index} data={item} index={index}></ListItem2>
                
            )
        })
        
        return (
            <div>
                <h1>
                    今天课程内容
                </h1>

                <ul>
                    {listArr}
                    <li>
                        <h3>这是标题</h3>
                        <p>内容</p>
                    </li>
                </ul>

                <h1>复杂没有用组件完成列表</h1>
                <ul>
                {
                    this.state.list.map((item,index)=>{
                        return (
                            <li key={index} onClick={(event)=>{this.clickFn(index,item.title,event)}}>
                                <h3>{index+1}-复杂-{item.title}</h3>
                                <p>{item.content}</p>
                            </li>
                        )
                    })
                }
                </ul>

            </div>
        )
    }

    clickFn=(index,title,event)=>{
        alert((index+1)+"-clickFn-"+title)
    }
}

生命周期

生命周期即是组件从实例化到渲染到最终从页面中销毁,整个过程就是生命周期,在这生命周期中,我们有许多可以调用的事件,也俗称为钩子函数

生命周期的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内容直接全部插入

class ParentCom extends React.Component{
    
    render(){
        console.log(this.props)
        return (
            <div>
                <h1>组件插槽</h1>
                {this.props.children}
            </div>
        )
    }
}

组件中根据HTML内容的不同,插入的位置不同。

import React from 'react';
import ReactDOM from 'react-dom';

class ParentCom extends React.Component{
    
    render(){
        console.log(this.props)
        return (
            <div>
                <h1>组件插槽</h1>
                {this.props.children}
                <ChildCom>
                    <h1 data-position="header">这是放置到头部的内容</h1>
                    <h1 data-position="main">这是放置到主要的内容</h1>
                    <h1 data-position="footer">这是放置到尾部的内容</h1>
                </ChildCom>
            </div>
        )
    }
}

class ChildCom extends React.Component{
    render(){
        let headerCom,mainCom,footerCom;
        this.props.children.forEach((item,index)=>{
           if(item.props['data-position']==='header'){
            headerCom = item
           }else if(item.props['data-position']==='main'){
               mainCom = item
           }else{
               footerCom = item
           }
        })
        return (
            <div>
                <div className="header">
                    {headerCom}
                </div>
                <div className="main">
                    {mainCom}
                </div>
                <div className="footer">
                    {footerCom}
                </div>
            </div>
        )
    }
}

class RootCom extends React.Component{
    constructor(props){
        super(props)
        //console.log(props)
        this.state = {
            arr:[1,2,3]
        }
    }
    render(){
        return (
            <ParentCom>
                <h2 data-name="a" data-index={this.state.arr[0]}>子组件1</h2>
                <h2 data-name="b" data-index={this.state.arr[1]}>子组件2</h2>
                <h2 data-name="c" data-index={this.state.arr[2]}>子组件3</h2>
            </ParentCom>
        )
    }
}

ReactDOM.render(
    <RootCom></RootCom>
    ,
    document.querySelector("#root")
)

React 路由

根据不同的路径,显示不同的组件(内容);React使用的库react-router-dom;

安装

Cnpm install react-router-dom --save

ReactRouter三大组件:

Router:所有路由组件的根组件(底层组件),包裹路由规则的最外层容器。

属性:basename->设置跟此路由根路径,router可以在1个组件中写多个。

Route:路由规则匹配组件,显示当前规则对应的组件

Link:路由跳转的组件

注意:如果要精确匹配,那么可以在route上设置exact属性。

Router使用案例

import React from 'react';
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/后端匹配使用
import {BrowserRouter as Router,Link,Route} from 'react-router-dom'

function Home(){
    return (
        <div>
            <h1>admini首页</h1>
        </div>
    )
}

function Me(){
    return (
        <div>
            <h1>admin个人中心</h1>
        </div>
    )
}

function Product(){
    return (
        <div>
            <h1>admin产品页面</h1>
        </div>
    )
}

class App extends React.Component{
    
    render(){
        return (
            <div id="app">
                {/* <div>所有页面普通内容</div> */}
                <Router>
                    <Route path="/" exact component={()=>(<div>首页</div>)}></Route>
                    <Route path="/me" component={()=>(<div>me</div>)}></Route>
                    <Route path="/product" component={()=>(<div>product</div>)}></Route>
                </Router>

                <Router>
                    {/* <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to="/me">个人中心</Link>
                    </div> */}
                    <Route path="/admin/" exact component={Home}></Route>
                    <Route path="/admin/product" component={Product}></Route>
                    <Route path="/admin/me" exact component={Me}></Route>
                </Router>
            </div>
        )
    }
}

export default App

Link组件可以设置to属性来进行页面的跳转,to属性可以直接写路径的字符串,也可以通过1个对象,进行路径的设置,如

render(){
        let meObj = {
            pathname:"/me",//跳转的路径
            search:"?username=admin",//get请求参数
            hash:"#abc",//设置的HASH值
            state:{msg:'helloworld'}//传入组件的数据
        };
        return (
            <div id="app">
                

                <Router>
                    <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to={ meObj }>个人中心</Link>
                    </div>
                    <Route path="/" exact component={Home}></Route>
                    <Route path="/product" component={Product}></Route>
                    <Route path="/me" exact component={Me}></Route>
                </Router>
            </div>
        )
    }

Linkreplace属性:点击链接后,将新地址替换成历史访问记录的原地址。

动态路由实现:

import React from 'react';
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/后端匹配使用
import {BrowserRouter as Router,Link,Route} from 'react-router-dom'

function Home(){
    return (
        <div>
            <h1>admini首页</h1>
        </div>
    )
}

function Me(props){
    console.log(props)
    return (
        <div>
            <h1>admin个人中心</h1>
        </div>
    )
}

function Product(){
    return (
        <div>
            <h1>admin产品页面</h1>
        </div>
    )
}

function News(props){
    console.log(props)
    return (
        <div>
            新闻页,新闻id:{props.match.params.id}
        </div>
    )
}

class App extends React.Component{
    
    render(){
        let meObj = {
            pathname:"/me",//跳转的路径
            search:"?username=admin",//get请求参数
            hash:"#abc",//设置的HASH值
            state:{msg:'helloworld'}//传入组件的数据
        };
        return (
            <div id="app">
                

                <Router>
                    <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to={ meObj }   replace>个人中心</Link>
                        <Link to="/news/4568789">新闻页</Link>
                    </div>
                    <Route path="/" exact component={Home}></Route>
                    <Route path="/product" component={Product}></Route>
                    <Route path="/me" exact component={Me}></Route>
                    <Route path="/news/:id" component={News}></Route>
                </Router>
            </div>
        )
    }
}

export default App

重定向组件

如果访问某个组件时,如果有重定向组件,那么就会修改页面路径,使得页面内容显示为所定向路径的内容

用例:

function LoginInfo(props){
    //props.loginState = 'success';
    //props.loginState = "fail"
    console.log(props)
    if(props.location.state.loginState === 'success'){
        return <Redirect to="/admin"></Redirect>
    }else{
        return <Redirect to="/login"></Redirect>
    }
}

Switch组件

switch组件内容的route只匹配1个,只要匹配到了,剩余的路由规则将不再匹配

class App extends React.Component{
    render(){
        return (
            <div>
                <Router>
                    <Switch>
                        <Route path="/" exact  component={()=>(<h1>首页</h1>)}></Route>
                        <Route path="/form" exact  component={FormCom}></Route>
                        <Route path="/login" exact  component={()=>(<h1>登录页</h1>)}></Route>
                        <Route path="/logininfo" exact component={LoginInfo}></Route>
                        <Route path="/admin" exact component={()=>(<h1>admin页,登录成功</h1>)}></Route>
                        <Route path="/abc" exact component={()=>(<h1>abc1页,登录成功</h1>)}></Route>
                        <Route path="/abc" exact component={()=>(<h1>abc2页,登录成功</h1>)}></Route>
                    </Switch>
                </Router>
            </div>
        )
    }
}

Redux

解决React数据管理(状态管理),用于中大型,数据比较庞大,组件之间数据交互多的情况下使用。如果你不知道是否需要使用Redux,那么你就不需要用它!

* 解决组件的数据通信。

* 解决数据和交互较多的应用

Redux只是一种状态管理的解决方案!

Store:数据仓库,保存数据的地方。

State:state1个对象,数据仓库里的所有数据都放到1state里。

Action:1个动作,触发数据改变的方法。

Dispatch:将动作触发成方法

Reducer:1个函数,通过获取动作,改变数据,生成1个新state。从而改变页面

安装

Cnpm install redux --save

初始化数据

//创建仓库
const store = createStore(reducer)
//用于通过动作,创建新的state
//reduce有2个作用,1初始化数据,第二个就是通过获取动作,改变数据
const reducer = function(state={num:0},action){
    console.log(action)
    switch(action.type){
        case "add":
            state.num++;
            break;
        case 'decrement':
            state.num--;
            break;
        default:
            break;
    }
    return {...state}//相当于对象的COPY
}

获取数据

let state = store.getState()

修改数据(通过动作修改数据)

//通过仓库的方法dispatch进行修改数据
store.dispatch({type:"add",content:{id:1,msg:"helloworld"}})

修改视图(监听数据的变化,重新渲染内容)

store.subscribe(()=>{
    ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
})

完整案例

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux'

//用于通过动作,创建新的state
const reducer = function(state={num:0},action){
    console.log(action)
    switch(action.type){
        case "add":
            state.num++;
            break;
        case 'decrement':
            state.num--;
            break;
        default:
            break;
    }
    return {...state}//相当于对象的COPY
}

//创建仓库
const store = createStore(reducer)
console.log(store)


function add(){
    //通过仓库的方法dispatch进行修改数据
    store.dispatch({type:"add",content:{id:1,msg:"helloworld"}})
    console.log(store.getState())
}
function decrement(){
    //通过仓库的方法dispatch进行修改数据
    store.dispatch({type:"decrement"})
    console.log(store.getState())
}
//函数式计数器
const Counter = function(props){
    //console.log(store.getState())
    let state = store.getState()
    return (
        <div>
            <h1>计数数量:{state.num}</h1>

            <button onClick={add}>计数+1</button>
            <button onClick={decrement}>计数-1</button>
        </div>
    )

}

ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
store.subscribe(()=>{
    ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
})

React-redux

安装

cnpm install react-redux --save

概念:

Provider组件:自动的将store里的state和组件进行关联。

MapStatetoProps:这个函数用于将storestate映射到组件的里props

mapdispatchToProps:store中的dispatch映射到组件的props里,实现了方法的共享。

Connect方法:将组件和数据(方法)进行连接

使用:

初始化数据,实例化store

function reducer(state={num:0},action){
    switch(action.type){
        case "add":
            state.num++;
            break;
        default:
            break;
    }
    return {...state}
}

const store = createStore(reducer)

数据的获取,数据的修改

state映射到到组件的props中,将修改数据的方法映射到组件的props

完整案例

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux';
import {connect, Provider} from 'react-redux'

class Counter extends React.Component{
    
    render(){
        console.log(this.props)
        //计数,通过stroe的state传给props,直接通过props就可以将state的数据获取
        const value = this.props.value;
        //将修改数据的事件或者方法传入到props
        const onAddClick = this.props.onAddClick;
        //等同于vuex的mapMutation mapState
        return (
            <div>
                <h1>计数的数量:{value}</h1>
                <button onClick={onAddClick}>数字+1</button>
                <button onClick={this.props.onAddClick5}>数字+5</button>
            </div>
        )


    }
}



let ActionFnObj={
    add:function(state,action){
        state.num++
        return state
    },
    addNum:function(state,action){
        
        state.num = state.num + action.num;
        return state
    }
}
function reducer(state={num:0},action){
    if(action.type.indexOf('redux')===-1){
        state = ActionFnObj[action.type](state,action)
        return {...state}
    }else{
        return state;
    }
    
    
}

const store = createStore(reducer)

//将state映射到props函数
function mapStateToProps(state){
    return {
        value:state.num
        
    }
}

const addAction = {
    type:'add'
}
//将修改state数据的方法,映射到props,默认会传入store里的dispach方法
function mapDispatchToProps(dispatch){
    return {
        onAddClick:()=>{dispatch(addAction)},
        onAddClick5:()=>{dispatch({type:"addNum",num:5})}
    }
}

//将上面的这2个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件。
const App = connect(
    mapStateToProps,
    mapDispatchToProps
)(Counter)

ReactDOM.render(
    <Provider store={store}>
        <App></App>
    </Provider>,
    document.querySelector("#root")
)

Ant 蚂蚁框架

npm install antd-mobile --save

按需要导入(自动导入用到的css样式):

  1. 安装插件
npm install  babel-plugin-import --save

2.配置

npm run eject

3.Packjson文件

"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["import", { "libraryName": "antd-mobile", "style": "css" }]
    ]
  }

其余参考官网

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部