起步

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. 2019牛客暑期多校训练营(第五场)H.subsequence 2(拓扑)

    题意:给你一个字符串的长度n 现在询问了m*(m-1)/2次 每次都可以询问两个字符 然后 会告诉你只留下这两个字符后 字符串的样子 现在问你能不能还原字符串 如果能就输出字符串 否则输出-1 思路: ...

  2. Codeforces Round #627 (Div. 3) D - Pair of Topics(双指针)

    题意: 有长为n的a,b两序列,问满足ai+aj>bi+bj(i<j)的i,j对数. 思路: 移项得:(ai-bi)+(aj-bj)>0,i<j即i!=j,用c序列保存所有ai ...

  3. POJ1113:Wall (凸包算法学习)

    题意: 给你一个由n个点构成的多边形城堡(看成二维),按顺序给你n个点,相邻两个点相连. 让你围着这个多边形城堡建一个围墙,城堡任意一点到围墙的距离要求大于等于L,让你求这个围墙的最小周长(看成二维平 ...

  4. Codeforces Round #653 (Div. 3) A. Required Remainder (数学)

    题意:有三个正整数\(x,y,n\),再\(1\)~\(n\)中找一个最大的数\(k\),使得\(k\ mod\ x=y\). 题解:先记\(tmp=n/x\),再判断\(tmp*x+y\)的值是否大 ...

  5. Cell 动态行高文字显示不全问题探索

    目录 问题概述 一.新建工程 二.尝试复现问题 尝试解决 修改contentLblBtmCon优先级为High(750) 修改contentLblBtmCon优先级为Low(250) 小结 其他解决思 ...

  6. [Golang]-3 函数、多返回值、变参、闭包、递归

    // test01 project main.go package main import ( "fmt" ) // 单返回值的函数 func plus(a int, b int) ...

  7. 操作系统:Linux进程与线程

    这里是一部分内容,还会做修改. 一:目的及内容 学习fork(),exec,pthread库函数的使用,阅读源码,分析fork,exec,pthread_create函数的机理 代码实现: 进程A创建 ...

  8. Postman查看上传文件过程时出现400 - Required MultipartFile parameter 'files' is not present错误

    我在利用postman查看上传图片文件时,出现了如下图的错误,看到之后很懵逼. 图1 上网搜了一下,归结下来就是参数不一致导致的.不过还有一些是由于没加注解,如下图示: 图2 关于参数不一致问题,主要 ...

  9. PAT L2-005. 集合相似度 【stl set】

    给定两个整数集合,它们的相似度定义为:Nc/Nt*100%.其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数.你的任务就是计算任意一对给定集合的相似度. 输入格式: 输 ...

  10. Python源码剖析——02虚拟机

    <Python源码剖析>笔记 第七章:编译结果 1.大概过程 运行一个Python程序会经历以下几个步骤: 由解释器对源文件(.py)进行编译,得到字节码(.pyc文件) 然后由虚拟机按照 ...