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上手非常简单,先看看几个例子: 例一: ...
随机推荐
- LightOJ - 1151 Snakes and Ladders(概率dp+高斯消元)
有100个格子,从1开始走,每次抛骰子走1~6,若抛出的点数导致走出了100以外,则重新抛一次.有n个格子会单向传送到其他格子,G[i]表示从i传送到G[i].1和100不会有传送,一个格子也不会有两 ...
- Redis的主从架构+哨兵模式
Redis主从架构 redis主从架构搭建,配置从节点步骤: 1.复制一份redis.conf文件的目录 cd /usr/local/java cp -a redis redis_6380 2.将相关 ...
- CentOS 7 架设LNMP动态网站
1.安装Nginx 1)使用Nginx官方的yum源 [root@localhost ~]# vim /etc/yum.repos.d/nginx.repo [nginx] name=nginx re ...
- C++中函数的形式参数引用
形式参数的传递方式 值传递 值传递是将数值传递到程序中,这种方式传递是单向传递 但是如果想要双向传递,这种视频无法满足: 引用传递 引用传递可以实现双向的传递 为了对比处两个之间的差异,这里举出两个例 ...
- windows信息收集
导语:介绍 特权升级总是被归结为适当的枚举.但要完成适当的枚举,你需要知道要检查和查找的内容.这通常需要伴随着经验的丰富而对系统非常熟悉.起初特权升级看起来像是一项艰巨的任务,但过了一段时间,你就 ...
- Linux内核实现透视---硬中断
Linux的中断处理是驱动中比较重要的一部分内容,要清楚具体的实现才能更好的理解而不是靠记住别人理解后总结的规律,所以今天就打算从从源码来学习一下Linux内核对于中断处理过程,设计中断子系统的初始化 ...
- 读写 LED 作业 台灯的 频闪研究1
读写 LED 作业 台灯的 频闪研究: 核心提示: 随着科技的持续发展,目前已经商业化的照明产品从第一代的白炽灯: 第二代的荧光灯.卤灯: 第三代的高强度气体放电灯; 以及当下主流的, 第四代的发光二 ...
- ES6 Set All In One
ES6 Set All In One Set 集合 Map 字典/地图 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Referenc ...
- CSS & new class name
CSS & new class name { test: /\.((s*)css|sass)$/, // test: /\.(css|scss|sass)$/, use: ExtractTex ...
- WebIDE All In One
WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...