起步

react 特点

  • 不使用模板
  • 不是一个mvc框架
  • 响应式
  • 轻量级的js库

原理

  • 虚拟dom 将dom抽象成js对象
  • diff算法

搭建开发环境

react.js 核心文件

react-dom.js 面向web端 渲染页面的dom 依赖于react核心文件

react-native 面向移动端app

babel.js 将es6 转换成es5 jsx转化成javascript

脚手架

npm install -g create-react-app
create-react-app -version 查看版本
create-react-app [projectName] //构建项目
npm start //启动

jsx语法

  • js+xml的组合
ReactDOM.render(<h1> hello world </h1>, document.getElementById("root"));
// document.getElementById("root")获取插入的容器
// jsx语法 <h1>hello world</h1> 遇到 <> 按照xml语法解析,遇到{} 按照js 语法解析

元素的渲染

function tick() {
const element = ( //括号--->需要显示多行标签时使用括号
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById('root'));
} setInterval(tick, 1000);

组件

//新建文件封装
import React from "react";
class App extends React.Component {
render() {
return ( //多行标签用()
<div>
<h1> Hello, world!!!!!!! </h1>
<h2> It is {new Date().toLocaleTimeString()}. </h2>
</div>
);
}
} export default App;
 import App from './App'
ReactDOM.render(<App />, document.getElementById("root"));

props

 //父组件中传入 des字段
ReactDOM.render(<App des="这是react框架" />, document.getElementById("root"));
//子组件中通过 this.props[字段名]获取数据
class App extends React.Component {
render() {
return (
<div>
<h1> Hello, world!!!!!!! {this.props.des}</h1>
<h2> It is {new Date().toLocaleTimeString()}. </h2>
</div>
);
}
}

state

constructor(props) {
super(props);
this.state = { //构造函数中定义state
count: 10,
};
} render() {
return (
<div>
<h1> Hello, world!!!!!!! {this.props.des}</h1>
<h2> It is {this.state.count}. </h2> //使用state中的变量
</div>
);
}

生命周期

)

  • componentWillMount:在组件渲染之前使用(beforeMount)
    conponentDidMount:渲染完成(mounted)
    componentUnMount:销毁组件 (beforeDestory)清除定时器等
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 10,
};
}
componentWillMount() {
console.log("componentWillMount");
}
componentDidMount() {
console.log("componentDidMount");
}
componentWillUnmount() {
console.log("componentWillUnmount");
}
shouldComponentUpdate() {
return true;
}
componentWillUpdate() {
console.log("componentWillUpdate");
}
componentDidUpdate() {
console.log("componentDidUpdate");
}
// componentWillReceiveProps() {
// console.log("componentWillReceiveProps");
// }
addCount = () => {
console.log(this.state)
//this.state.count += 1;
this.setState({
count: (this.state.count += 1),
});
};
render() {
return (
<div>
<h1> Hello, world!!!!!!! {this.props.des}</h1>
<h2> It is {this.state.count}. </h2>
<button onClick={this.addCount}>增加</button>
</div>
);
}
} export default App;
  • 由上图可知:

    • 单纯渲染组件时 componentWillMount--->componentDidMount

    • 改变state时:shouldComponentUpdate(返回true允许改变,否则不继续运行)---> componentWillUpdate--->componentDidUpdate

    • 由于props是单向传递,当父组件改变props时,触发子组件componentWillReceiveProps函数,

      componentWillReceiveProps-->shouldComponentUpdate(返回true允许改变,否则不继续运行)---> componentWillUpdate--->componentDidUpdate

  • 注:this.state.count += 1;这种直接改变state不会去刷新组件,自然也不会触发生命周期函数,使用setState函数改变state才会重新渲染组件

数据的子传父与父传子

父传子
//父组件
import App from "./App.jsx";
ReactDOM.render(<App des="这是react框架" />, document.getElementById("root")); //组件中自定义属性
//子组件
//构造器
constructor(props) {
super(props); //super接受props对象
this.state = {
count: 10,
};
}
//
render() {
return (
<div>
<h1> Hello, world!!!!!!! {this.props.des}</h1> 通过this.props调用对应的属性
<h2> It is {this.state.count}. </h2>
<button onClick={this.addCount}>增加</button>
</div>
);
}
子传父
  • (利用事件的回传,类似vue中的$emit自定义事件)
//父组件中
//构造器中定义变量
constructor() {
super();
this.state={
title:'123'
}
}
//定义所要触发的事件
changeCount = (data) => {
this.setState({
title: data,
});
};
//组件中传递props
<Mycomponent title={this.state.title} clickChange={this.changeCount}></Mycomponent>

子组件可以看到父组件传递的props:

)

//子组件中
//定义事件
addCount = () => {
this.props.clickChange('子组件传递来的参数');//形参传递给父组件,父组件接收后改变state,然后回传给子组件,子组件重新渲染
};
//渲染
render() {
return (
<div>
<h1> Hello, world!!!!!!! {this.props.title}</h1>
<button onClick={this.addCount}>增加</button> //传入子组件中定义的事件,然后再触发该事件里面父组件自定义的clickChange事件
</div>
);
}

条件渲染

  //构造器state中定义isLogin变量
this.state = {
count: 10,
isLogin: false,
};
//渲染的时候
changeLogin = () => {
this.setState({
isLogin: true,
});
};
render() {
const { isLogin } = this.state;
let login = isLogin ? <div>已登陆</div> : <div>未登陆</div>;
return (
<div>
{login} //
<button onClick={this.changeLogin}>改变登陆状态</button>
</div>
);
}

列表渲染

//state中定义一个数组对象
userInfo: [
{
name: "张三",
age: 12,
},
{
name: "李四",
age: 13,
},
{
name: "王五",
age: 14,
},
], //render中遍历数组对象进行渲染
render() {
return (
<div>
<ul>
{this.state.userInfo.map((el,index) => {
return (
<li key={index}> //注意在最外层添加key,否则会产生警告
<span>{el.name}</span>
<span>{el.age}</span>
</li>
);
})}
</ul>
</div>
);
}

)

ref

//构造器中创建ref
constructor(props) {
super(props);
this.myRef = React.createRef();
}
//访问ref 通过current属性获取dom对象
this.myRef.current.style.color="red"

受控组件与非受控组件

受控组件
//state动定义
this.state = {
value: "",
value2: "",
value3: "",
};
//改变时通过e.target获取值
changeVaue = (e) => {
this.setState({
value: e.target.value,
});
};
changeVaue2 = (e) => {
this.setState({
value2: e.target.value,
});
};
changeVaue3 = (e) => {
this.setState({
value3: e.target.value,
});
};
//对input的值进行更新
<input
type="text"
value={this.state.value}
onChange={this.changeVaue}
/>
<input
type="text"
value={this.state.value2}
onChange={this.changeVaue2}
/>
<input
type="text"
value={this.state.value3}
onChange={this.changeVaue3}
/>
非受控组件
  • 当表单的重复工作太多,数据变化的每种方式都编写事件处理函数,比如上面受控组件的情况,这个时候用非受控组件可以很好的解决
  //构造器中创建变量,和ref来操作dom
this.state = {
value1: "",
value2: "",
value3: "",
};
this.myValue1 = React.createRef();
this.myValue2 = React.createRef();
this.myValue3 = React.createRef();
//将值与ref节点一一对应
<input type="text" ref={this.myValue1} />
<input type="text" ref={this.myValue2} />
<input type="text" ref={this.myValue3} />
//提交时获取state的值
this.myValue1.current.value //

状态提升

  • 通过一个父组件来管理多个子组件中的数据
//父组件
import React from "react";
import MyComponent from "./component";
import MyForm from "./form";
import Child1 from "./component/child1";
import Child2 from "./component/child2"; class App extends React.Component {
constructor() {
super();
this.state = {
money: 8, };
}
handleChange = (e) => {
this.setState({
money: e.target.value,
});
};
render() {
return (
<div>
<input type="text" value={this.state.money} onChange={this.handleChange} />
¥:<Child1 money={this.state.money}></Child1>
$:<Child2 money={this.state.money}></Child2>
</div>
);
}
}
export default App;
//自组件
import React from "react";
export default class Child1 extends React.Component {
constructor() {
super(); } render() {
return (
<p>{this.props.money }</p>
);
}
}

组件的组合

  • 类似vue的slot插槽
//父组件
<Child1 money={this.state.money}>
<span>组件的组合</span>
</Child1> //子组件 通过this.props.children调用
<p>
{this.props.children}
</p>

PropsTypes类型检查(poprs)

import React from "react";
import PropTypes from "prop-types";
export default class Child1 extends React.Component {
constructor() {
super();
} render() {
return <p>{this.props.money}</p>;
}
} //定义传入props的参数类型
Child1.PropTypes = {
money:PropTypes.number, //number类型
sex:PropTypes.string.isRequired, //string类型,必选
};
// 指定 props 的默认值:
Child1.defaultProps = {
name: 'Stranger'
};

路由

安装

npm install react-router-dom --save

基础

//两个子路由
//Mine.jsx
import React from "react";
export default class Mine extends React.Component {
render() {
return <div>Mine</div>;
}
}
//Home.jsx
import React from "react";
export default class Home extends React.Component {
render() {
return <div>Home</div>;
}
}
//App.jsx
import Home from "./pages/Home";
import Mine from "./pages/Mine";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class App extends React.Component {
render() {
return (
<div>
<Router>
<Route path="/home" component={Home}></Route>
<Route path="/mine" component={Mine}></Route>
</Router>
</div>
);
}
}

两种路由类型

  • 哈希类型(HashRouter) 锚点链接
  • History(BrowserRouter)h5新特性 history.push()来实现
import { BrowserRouter as Router } from "react-router-dom"; //使用history模式
x import { HashRouter as Router } from "react-router-dom"; //使用hash模式

路由的跳转

import { HashRouter as Router, Route, Link } from "react-router-dom";//引入Link组件
//使用
<Router>
<ul>
<li>
<Link to="/home">Home页面</Link> //导航地址
</li>
<li>
<Link to="/mine">Mine页面</Link>
</li>
</ul>
<Route path="/home" component={Home}></Route>
<Route path="/mine" component={Mine}></Route>
</Router>

路由的匹配问题

exact:bool
  • 现在有两个路径 /person/man/person,

  • 默认情况下 跳转到/person/man时,也会匹配到person

    //解决方法   使用exact来实现精准匹配
    <Route exact={true} path="/person" component={人类}></Route>
    <Route path="/person/man" component={男人}></Route>
strict:bool
  • 更为严格的匹配方式,将地址末尾有 /与无 / 的情况当作两个地址

react入个门的更多相关文章

  1. webpack实践(一)- 先入个门

    一.前言   webpack是个啥呢?看官网的这段描述. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)   在我以前做纯html.css. ...

  2. react 入坑笔记(四) - React 事件绑定和传参

    React 事件处理 建议:在了解 js 的 this 取值后食用更佳. 一.react 与 Html 中用法的异同和注意点 html 中的绑定事件的写法: <button onclick=&q ...

  3. react 入坑笔记(六) - 组件的生命周期

    React 组件生命周期 详细参考: react 组件生命周期 组件的生命周期可分为三个状态: 1.Mounting:已经挂载/插入到真实 DOM 树上: 2.Updating:正在被重新渲染: 3. ...

  4. react 入坑之罪

    componentDidMount :生命周期在react下只调用一次, render:比它先执行 componentWillRecvieProps(newProps) :能取到父组件的值 rende ...

  5. react 入坑笔记(五) - 条件渲染和列表渲染

    条件渲染和列表渲染 一.条件渲染 条件渲染较简单,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI. 贴一个小栗子: funct ...

  6. react 入坑笔记(三) - Props

    React Props props - 参数. 组件类 React.Component 有个 defaultProps 属性,以 class xxx extend React.Component 形式 ...

  7. react 入坑笔记(二) - State

    React State 一. state 大致思想:在 react 中,每个组件都是一个状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致.React 里,只需更新组件的 ...

  8. react 入坑笔记(一)

    一些概念: 1.组件:概念等同于 vue 中的组件,字面意思,不过 vue 中组件是以 .vue 结尾,通过 vue-loader 编译成 js,而 react 组件就是 js. 2.jsx:js 语 ...

  9. Vue.js先入个门看看

    使用vue.js原文介绍:Vue.js是一个构建数据驱动的web界面库.Vue.js的目标是通过尽可能简单的API实现响应式数据绑定和组合的视图组件.vue.js上手非常简单,先看看几个例子: 例一: ...

随机推荐

  1. Codeforces Round #638 (Div. 2)

    Contest Info Practice Link Solved A B C D E F 4/6 O O Ø  Ø     O 在比赛中通过 Ø 赛后通过 ! 尝试了但是失败了 - 没有尝试 Sol ...

  2. 2018-2019 ACM-ICPC Brazil Subregional Programming Contest PART (10/13)

    $$2018-2019 ACM-ICPC Brazil Subregional Programming Contest$$ \(A.Slackline\ Adventure\) \(B.Marbles ...

  3. poj3415 Common Substrings (后缀数组+单调队列)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9414   Accepted: 3123 Description A sub ...

  4. Alice's mooncake shop HDU - 4122 单调队列

    题意: 有n个订单和可以在m小时内制作月饼,制作月饼不考虑时间(即,你可以在一个时刻在所有需要的月饼都做完) 接下来是n个订单的信息:需要在mon月,d日,year年,h小时交付订单r个月饼 接下来一 ...

  5. Codeforces Round #671 (Div. 2) B. Stairs (递推)

    题意:一个台阶由一些单元格组成,如果一个高度为\(n\)的台阶中有\(n\)个不相邻的正方形(如图中的样例),就称这个台阶是"好台阶",现给你\(x\)个单元格,问最多能组成多少个 ...

  6. hdu 4497 GCD and LCM (非原创)

    GCD and LCM Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

  7. 2019牛客多校第九场B Quadratic equation(二次剩余定理)题解

    题意: 传送门 已知\(0 <= x <= y < p, p = 1e9 + 7\)且有 \((x+y) = b\mod p\) \((x\times y)=c\mod p\) 求解 ...

  8. Java中Class.forName()用法和newInstance()方法详解

    1.Class.forName()主要功能 Class.forName(xxx.xx.xx)返回的是一个类, Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就 ...

  9. GUI编程

    组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事 破解工具 简介 GUI的核心技术:Swing AWT 界面不美观 需要jre环境 为了了解MVC架构 了解监听. AWT 包 ...

  10. Vue & Sentry

    Vue & Sentry config.errorHandler https://cn.vuejs.org/v2/api/#errorHandler Vue.config.errorHandl ...