起步

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. CF Hello 2020 E.New Year and Castle Construction

    E.New Year and Castle Construction 题意 给定n个点,对于每个点\(p\),求出4-point 子集(该子集有四个点,并且围成的圈包含\(p\))的个数 数据给的点中 ...

  2. 【noi 2.6_2421】Exchange Rates(DP)

    题意:起始有1000元美元,给出N天美元与加拿大元的汇率.问N天内可以不停的兑换,每次兑换需要收取3%的手续费,问可以得到的最大的美元数. 解法:直接用2个变量存第 i 天时手中是美元和加拿大元的最大 ...

  3. .net面试--值类型和引用类型

    注:下面的示意图主要是为了辅助理解,不代表内存真实情况. Introduction 类型基础是C#的基础概念,了解类型基础及背后的工作原理更有助于我们在编码的时候明白数据在内存中的分配与传递.C#提供 ...

  4. 浅谈Webpack模块打包工具二

    Webpack插件机制介绍 Loader专注实现资源模块加载,plugin解决其他自动化工作,比如清除dist目录,拷贝静态文件值输出目录,压缩输出代码等,下面列举几个plugin 的例子. Webp ...

  5. Python 往Excel写数据

    一.需求描述: 1.一张人员信息表中生成人员信息,某些列的字段要进行递增操作: 2.一个组织节点下存在1000人的限制要求: 3.一张Excel表格生成45000条数据: 二.Excel表格的表头如下 ...

  6. k8s二进制部署 - etcd节点安装

    下载etcd [root@hdss7-12 ~]# useradd -s /sbin/nologin -M etcd [root@hdss7-12 ~]# cd /opt/src/ [root@hds ...

  7. kubernetes实战-配置中心(一)configmap资源

    在我们的环境中测试使用configmap资源,需要先对我们的环境进行一些准备,首先将dubbo服务调整为0个pod ,然后把zookeeper进行拆分: 拆分zk环境,模拟测试环境跟生产环境: 停止z ...

  8. WOJ1022 Competition of Programming 贪心 WOJ1023 Division dp

    title: WOJ1022 Competition of Programming 贪心 date: 2020-03-19 13:43:00 categories: acm tags: [acm,wo ...

  9. Linux 驱动框架---驱动中的中断

    在单片机开发中中断就是执行过程中发生了一些事件需要及时处理,所以需要停止当前正在运行的处理的事情转而去执行中断服务函数,已完成必要的事件的处理.在Linux中断一样是如此使用但是基于常见的中断控制器的 ...

  10. 写给程序员的机器学习入门 (十一) - 对象识别 YOLO - 识别人脸位置与是否戴口罩

    这篇将会介绍目前最流行的对象识别模型 YOLO,YOLO 的特征是快,识别速度非常快