React学习笔记

2018-07-12  本文已影响0人  爱翔是我二媳妇

create-react-app

通过创建一个已经完成基本配置的应用,让开发者快速开始React应用的开发。

安装

npm install --global create-react-app

安装后可执行create-react-app 项目名操作。
以上操作后会在当前目录下创建一个first_react_app目录,目录中自动添加一个应用的框架,我们只需要修改文件即可。

之后输入命令:

cd first_react_app
npm start

这个命令会启动 个开发模式的服务器,同时也会让你的浏览器自动打开了 个网页,指向本机地址 http://localhost:3000

感觉create-react-app类似于vue中的vue-cli,即满足热刷新和项目架构的搭建。

JSX语法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="reactContainer"></div>
</body>
<script src="react.js"></script>
<script src="react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
<script type="text/babel">
    var HelloComponent = React.createClass({
        render:function(){
            return <h1>Hello { this.props.name ? this.props.name:"world" }</h1>;
        }
    });

    ReactDOM.render(
        <HelloComponent name="nijiagugu"/>,
        document.getElementById("reactContainer")
    )
</script>
</html>

state

state是一个状态集合,开发者的主要工作就是定义state,并根据不同的state渲染对应的用户界面。

以下通过一个点击按钮切换input可用性的例子来解析state。

初始化state

这里我所理解的state,就是Vue中的data数据,在其他方法中访问时需要加上this.state

getInitialState: function(){
    return {enable:true};
}

添加事件处理方法
点击切换可用性。

 handleClick:function(event){
    this.setState({enable:!this.state.enable})
}

挂载

ReactDOM.render(
    <HelloComponent/>,
    document.getElementById("reactContainer")
)

全部代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="reactContainer"></div>
</body>
<script src="react.js"></script>
<script src="react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
<script type="text/babel">
    var HelloComponent = React.createClass({
        getInitialState: function(){
            return {enable:true};
        },
        handleClick:function(event){
            this.setState({enable:!this.state.enable})
        },
        render:function(){
            // return <h1>Hello { this.props.name ? this.props.name:"world" }</h1>;
            return (
                <p>
                    <input type="text"  disabled={this.state.enable}/>
                    <button onClick={this.handleClick}>改变可用性</button>
                </p>
            )
        }
    });

    ReactDOM.render(
        <HelloComponent/>,
        document.getElementById("reactContainer")
    )
</script>
</html>

props

实际上就是属性值,可通过在标签中通过属性名="属性值"设置。

生命周期

componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()

子属性

props属性验证

通过propsTypes进行属性验证。如我们获取的父级元素的值的属性必须要不为空,onClick必须是函数等限定。

用法

propTypes:{
    title:React.PropTypes.string.isRequired,
}

PropTypes告诉React,这个title属性是必须的,而且它的值必须是字符串。

否则,会在控制台报Warning。

propTypes的更多设置

//TODO

props默认属性值

getDefaultProps

getDefaultProps:function(){
    return {
        title:'Hello JSPang'
    }
},
render:function(){
    return(
        <h2>{this.props.title}</h2>
    )
}

获取真实Dom节点

react是虚拟的DOM的节点,只渲染变化的部分。

ref可简单的理解为id来获取当前节点。

var AddCount=React.createClass({
    render:function(){
        return(
            <div>
                <input type="text" ref="myTextInput"/>
                <input type="button" value="Focus mouse" onClick={this.handleClick}/>
            </div>
        )
    },
    handleClick:function(){
    this.refs.myTextInput.focus();
    }
})
ReactDOM.render(
    <AddCount/>,
    document.getElementById("demo")
);

react表单

自动监控表单内容变化

通过state和onChange事件来触发数据的响应变化。

实现

var  MyForm = React.createClass({
    getInitialState:function(){
    return{
        value:"hello"
    }
    },
    handleChange:function(event){
        this.setState({value:event.target.value});
    },
    render:function(){
        var value = this.state.value;
        return (
            <div>
                <p>{ value }</p>
                <input type="text" value={ value } onChange={ this.handleChange } />
            </div>
        )
    }
});


ReactDOM.render(<MyForm/>,document.getElementById('demo'))

可控组件

render中设置inputvalue是不可以改变的。

var  MyForm = React.createClass({
    render:function(){
        return (
            <div>
                <input type="text" value="hello" />
            </div>
        )
    }
});

ReactDOM.render(<MyForm/>,document.getElementById('demo'));

必须通过state的方式绑定初始值。
通过onChange绑定事件。
可控组件就是value必须绑定到state上,必须监控onChange事件,实时监控。

不可控组件

不可控组件是不绑定state值,虽然可以通过onChange监听变化,但是需要获取他的DOM

generator-react-webpack

一款集成了webpack的脚手架。但是需要yeoman的支持

安装

npm install -g yo
npm install -g generator-react-webpack

创建目录

mkdir new-react-demo
cd new-react-demo

生成项目目录

yo react-webpack

起服务

npm start

用webpack配置react开发环境

  1. 项目初始化
npm init
  1. 安装webpack
npm install --save-dev webpack
  1. 配置webpack.config.js
    创建webpack.config.js文件
var path =require('path');
module.exports = {
    //入口文件
    entry:'./app/index.js',
    //出口文件
    output:{
        filename:'index.js',
        path:path.resolve(__dirname,'dist')
    }
}
  1. 创建dist目录、app目录、app目录下的index.js文件、根目录下创建index.html
    index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ReactWebpack</title>
</head>
<body>
    
</body>
<script src="./dist/index.js"></script>
</html>

这里引入的是出口文件

  1. 在packge.json中加入build命令
"scripts": {
    "build": "webpack"
  },
  1. 配置服务器
cnpm install --save-dev webpack-dev-server

在webpack.config.js中配置

devServer:{
    contentBase:'./',
    host:'localhost',
    compress:true,
    port:1717
}
  1. 在packeage.js添加script命令
 "scripts": {
    "build": "webpack",
    "server": "webpack-dev-server --open"
  },
  1. 配置自动刷新
    在webpack.config.js中的output中添加一项配置
output:{
    filename:'index.js',
    path:path.resolve(__dirname,'dist'),
    publicPath:'temp/'
},

在index.html中修改script引用路径为./temp/index.js

重启服务器即可实现自动刷新。

  1. Babel安装
cnpm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
  1. 配置module
module:{
    rules:[
        {
            test:/\.js$/,
            exclude:/node_modules/,
            loaders:"babel-loader",
            query:{
                presets:['es2015','react']
            }
        }
    ]
}
  1. 安装react
cnpm install react react-dom
  1. 修改app/index.js
import React from "react"
import ReactDOM from "react-dom"

ReactDOM.render(
    <div>Hello world</div>,
    document.getElementById("app")
);

打包命令

npm run --dev=dist

路由

安装路由

npm install --save react-router react-router-dom

两个包都可以运行,但是React-router包括Router、Route、Switch等,但是没有提供DOM操作进行跳转的api。
React-router-dom可以通过DOM事件控制路由进行跳转。

  1. 通过es6的继承写法新建一个自定义组件
    gugu.js
import React from "react"
export default class gugu extends React.Component{
    render(){
        return(
            <div>A默认页面</div>
        )
    }
}
  1. 在app/index.js下引入自定义组件
import Gugu from "./gugu"
  1. 新建一些差不多的组件以便后面路由使用
import Gugu from "./gugu"
import Gugua from "./gugua"
import Gugub from "./gugub"
  1. 引入路由
    在index.js中写:
import {BrowserRouter as Router,Route} from "react-router-dom"

Router相当于一个容器,Router是一个路由

修改(编写)路由:

ReactDOM.render(
    <Router>
        <div>
            {/* exact是这里的exact是精确匹配的意思,比如我们有多层路由进行嵌套时,exact可以帮助我们精确匹配到你想跳转的路由。 */}
            <Route exact path="/" component={Gugu} />
            <Route  path="/Gugua" component={Gugua} /> 
            <Route  path="/Gugub" component={Gugub} />
        </div>
    </Router>,
    document.getElementById("app")
);
  1. 编辑导航Nav
    新建一个组件nav.js
import React from "react"
import {NavLink} from "react-router-dom" 
const Nav = () =>(
<div>
    <div>
        <NavLink exact to='/'>Gugu</NavLink> | 
        <NavLink to='/Gugua'>Gugua</NavLink> | 
        <NavLink to='/Gugub'>Gugub</NavLink>
    </div>
</div>
)
   
export default Nav;
  1. 在app/index.js中挂载这个组件
import Nav from "./nav"


ReactDOM.render(
    <Router>
        <div>
            <Nav/>
            {/* exact是这里的exact是精确匹配的意思,比如我们有多层路由进行嵌套时,exact可以帮助我们精确匹配到你想跳转的路由。 */}
            <Route exact path="/" component={Gugu} />
            <Route  path="/Gugua" component={Gugua} /> 
            <Route  path="/Gugub" component={Gugub} />
        </div>
    </Router>,
    document.getElementById("app")
);

直接输入url是无法访问路由的

NavLink

给NavLink加样式。

  1. 增加一个nav.css文件
.blue{
    color: red;
}
  1. 在nav.js中引入
import "./nav.css"
  1. 配置webpack
    安装style-loader
cnpm install --save-dev style-loader css-loader

在webpack.config.js中添加配置

{
    test:/\.css$/,
    loader:['style-loader','css-loader']
}

NavLink中的active
指的链接的激活状态。

<div>
    <div class="blue">
        <NavLink exact to='/' activeClassName="bbb">Gugu</NavLink> | 
        <NavLink to='/Gugua' activeClassName="bbb">Gugua</NavLink> | 
        <NavLink to='/Gugub' activeClassName="bbb">Gugub</NavLink>
    </div>
</div>

activeClassName为激活状态应用的类名。

HashRouter和BrowserRouters

HashRouter会让URL中默认有一个井号(#),而BrowserRouter则不会有这个井号(#)

Link和NavLink

两者都是可以控制路由跳转的,不同点是NavLink的api更多,更加满足你的需求。
NavLink它可以为当前选中的路由设置类名、样式以及回调函数等。

match

用于页面传参。

/second/:id

在新的路由页面中获取这个id,需要用到match。

获取的时候用this.props.match.params.id,id是之前定义好的属性值。
多参数传递
此种方式不常用,但可以实现

/second/:id/:name

之后可通过this.props.match.params.id,this.props.match.params.name获取。

404设置

利用switch

  1. 在index.js中引入Switch
import {BrowserRouter as Router,Route,hashHistory,HashRouter,Switch} from "react-router-dom"
  1. 创建一个不存在的NavLink
<Link to='/Gusdb' activeClassName="bbb">404</Link>
  1. 引入404组件,并为其配置路由
import Error from "./nomatch"


ReactDOM.render(
    <Router history={hashHistory}>
        <div>
            <Nav/>
            {/* exact是这里的exact是精确匹配的意思,比如我们有多层路由进行嵌套时,exact可以帮助我们精确匹配到你想跳转的路由。 */}
            <switch>
                <Route exact path="/" component={Gugu} />
                <Route  path="/Gugua/:id" component={Gugua} /> 
                <Route  path="/Gugub" component={Gugub} />
                <Route  component={Error}/>
            </switch>
        </div>
    </Router>,
    document.getElementById("app")
);

switch中,404页面必须放在最下方。

Redirect跳转

在开发中有时候遇到根据业务逻辑进行跳转,需要用到Redirect,但是Redirect必须有Switch的支持

  1. 引入Redirect
import {BrowserRouter as Router,Route,hashHistory,HashRouter,Switch,Redirect} from "react-router-dom"
  1. 加入跳转链接
    <Link to='/redirect' activeClassName="bbb">Redirect</Link>
  1. 加入<Redirect>标签
    在index.js中添加标签。
<Redirect from="/redirect" to="/" />

路由的其他属性

basename
增加路由层级。
forceRefresh
强制刷新

forceRefresh={true}

加上他,路由将会失效。

路由模式

BrowserRouter:浏览器的路由方式,也是我们一直在学习的路由方式,在开发中最常使用。
HashRouter:在路径前加入#号成为一个哈希值。Hash模式的好处是,再也不会因为我们刷新而找不到我们的对应路径了。
MemoryRouter:不存储history,所有路由过程保存在内存里,不能进行前进后退,因为地址栏没有发生任何变化。
NativeRouter:经常配合ReactNative使用,多用于移动端
StaticRouter:设置静态路由,需要和后台服务器配合设置,比如设置服务端渲染时使用。

Prompt标签

react-router提供的一个标签,提示的意思。

import React from "react"
import {Prompt} from 'react-router-dom';
export default class gugub extends React.Component{
    render(){
        return(
            <div>
                <div>bb默认页面</div>
                <Prompt message="残忍离开?"/>
            </div>
        )
    }
}
上一篇 下一篇

猜你喜欢

热点阅读