react入个门
起步
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入个门的更多相关文章
- webpack实践(一)- 先入个门
一.前言 webpack是个啥呢?看官网的这段描述. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) 在我以前做纯html.css. ...
- react 入坑笔记(四) - React 事件绑定和传参
React 事件处理 建议:在了解 js 的 this 取值后食用更佳. 一.react 与 Html 中用法的异同和注意点 html 中的绑定事件的写法: <button onclick=&q ...
- react 入坑笔记(六) - 组件的生命周期
React 组件生命周期 详细参考: react 组件生命周期 组件的生命周期可分为三个状态: 1.Mounting:已经挂载/插入到真实 DOM 树上: 2.Updating:正在被重新渲染: 3. ...
- react 入坑之罪
componentDidMount :生命周期在react下只调用一次, render:比它先执行 componentWillRecvieProps(newProps) :能取到父组件的值 rende ...
- react 入坑笔记(五) - 条件渲染和列表渲染
条件渲染和列表渲染 一.条件渲染 条件渲染较简单,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI. 贴一个小栗子: funct ...
- react 入坑笔记(三) - Props
React Props props - 参数. 组件类 React.Component 有个 defaultProps 属性,以 class xxx extend React.Component 形式 ...
- react 入坑笔记(二) - State
React State 一. state 大致思想:在 react 中,每个组件都是一个状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致.React 里,只需更新组件的 ...
- react 入坑笔记(一)
一些概念: 1.组件:概念等同于 vue 中的组件,字面意思,不过 vue 中组件是以 .vue 结尾,通过 vue-loader 编译成 js,而 react 组件就是 js. 2.jsx:js 语 ...
- Vue.js先入个门看看
使用vue.js原文介绍:Vue.js是一个构建数据驱动的web界面库.Vue.js的目标是通过尽可能简单的API实现响应式数据绑定和组合的视图组件.vue.js上手非常简单,先看看几个例子: 例一: ...
随机推荐
- A - 最长回文(马拉车算法//manacher)
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符串,如aba, abba等 Input输入有多组case,不超过120组,每组输入为一 ...
- The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)
题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...
- hdu5886Tower Defence(树形dp)
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- Codeforces Round #652 (Div. 2) C. RationalLee 贪心
题意: t组输入,你有n个数,还有k个朋友,每一个朋友需要wi个数.意思就是你要给第i个朋友分配wi个数,输入保证w1+w2+...+wk=n 一个朋友的兴奋值是你分配给他的数中最大值加上最小值的和( ...
- Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal (思维,逆序对)
题意:给你一个字符串,每次可以调换现字符串的相邻两个字符,问最少操作多少次使得这个字符串等于其反转过来的字符串. 题解:先考虑字符串中没有相同字符的情况,那么我们每次将目前字符串的最后一个字符一直调换 ...
- 在WLS2下开发和部署NET Core3.1目录
前言 在youtube推送上看到WSL2的消息(https://www.youtube.com/watch?v=MrZolfGm8Zk&t=1s),觉得很棒.恰好最近在学习PowerShell ...
- 包机制和javadoc
包机制 一般用公司域名倒置作为包名: eg com.baidu.www 可以在src里自己鼠标右键建立包,包内可以存放代码, 包的路径必须在最上面, eg:package com.kuang; (自动 ...
- Pangolin 安装测试 Installation & Examination (Ubuntu 20.04)
Pangolin 安装测试 Installation & Examination (Ubuntu 20.04) 如题所述,这是一个比较轻松的 Pangolin 安装配置方法,同样是基于 WSL ...
- Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...
- pikachu-反射性xss(get)
首先打开漏洞网页,发现输入的长度好像被限制了, 我们便F12查看源代码,发现长度被限制成了20,而且还是前端验证的,我们可以直接修改为100 在我们的输入框中,输入 <script>ale ...