React学习笔记

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>
        )
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 学习目的 熟练使用 React,并能运用 React 做一个项目,了解 React 开发。 学习技巧,用学...
    _1633_阅读 513评论 0 1
  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,804评论 0 24
  • React 核心思想 —— 组件化React 将界面分成了一个个组件,通过组件的组合、嵌套构成页面。其中,组件可复...
    sylvia_yue阅读 1,041评论 1 2
  • Learn from React 官方文档 一、Rendering Elements 1. Rendering a...
    恰皮阅读 2,659评论 2 3
  • 安装: 概述 React起源于FaceBook的内部项目,因为该公司对市场上所有的JavaScript MVC框架...
    姒沝無痕阅读 709评论 0 0