React 学习笔记(1) 基础语法和生命周期
参看:视频地址
简单搭建一个react-cli:
2. React.createElement()
将object转化为 React语法
import React from 'react'
import ReactDOM from 'react-dom' /**
* React.createElement()
* 参数1: 标签名
* 参数2: 标签属性
* 参数3: 标签内容
* 参数4: 其他节点
*/
// 需要 babel loader 解析jsx语法
const myH1 = <div title='h1'>哈哈哈</div> const myDiv = React.createElement('div', { title: 'this is a div', id: 'mydiv' }, '这是一个div', myH1) // 将 myH1 放在 myDiv中,渲染到 #app 标签中
ReactDOM.render(myDiv, document.getElementById('app'))
React.createElement()
3. jsx 语法
3.1 jsx语法的配置
jsx语法不能直接使用,需要@babel/preset-react翻译。
// package.json
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/preset-env": "^7.6.2",
"@babel/preset-react": "^7.0.0",
"@babel/runtime": "^7.6.2",
"babel-loader": "^8.0.6",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2"
},
"dependencies": {
"react": "^16.10.2",
"react-dom": "^16.10.2"
}
// .babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/transform-runtime", "@babel/plugin-proposal-class-properties"]
}
// webpack.config.js
const path = require('path')
const HtmlWebPackPlugin = require('html-webpack-plugin') const htmlPlugin = new HtmlWebPackPlugin({
template: path.join(__dirname, './src/index.html'),
filename: 'index.html'
}) module.exports = {
mode: 'development', // development production
plugins: [
htmlPlugin
],
module: {
rules: [
// 解析 jsx 语法
{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
},
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.json']
}
}
3.2 语法
原生标签比如
p、li、div如果要使用自定义属性,必须用data-前缀
样式使用双大括号
import React, { Component } from "react"
export default class User extends Component {
render() {
const num = 100 // 数字
const str = "react 学习" // 字符串
const bool = true // 布尔值
const unde = undefined // undefined
const nu = null // null
const h4dom = <h4 style={{"width":"100px","height":20 + 30 + "px","backgroundColor" : "red"}}>这是一个h4标签</h4> // jsx 语法
// 遍历数组
const arrDom = [
<h5 key="1">这是一个h5标签1</h5>,
<h5 key="2">这是一个h5标签2</h5>,
<h5 key="3">这是一个h5标签3</h5>
]
// 字符串数组
const arr = ["白板", "幺鸡", "二条", "三饼"]
return (
<div>
{num + 1} - {str} - {bool.toString()} - {unde} - {nu}
<h3 title={str}>这是一个h3标签</h3>
{/* 数组会自动展开 */}
{h4dom}
{arrDom}
<hr />
{arr}
</div>
)
}
}
4. 创建组件
组件名必须大写
组件方法必须
return
4.1 构造函数创建组件--无状态组件
import React, { Component } from "react"
// 将 person 传入 Stu 组件中 --- 子组件
// 使用 props 接收传进来的参数; props 只读,不可更改
function Stu(props) {
return (
<h1 style={{ color: "red", fontSize: 20 }}>
{/* 接受父组件传递过来的值 */}
Holle World: {props.name} - {props.age} - {props.gender}
</h1>
)
}
// 父组件
export default class User extends Component {
render() {
const person = {
name: "Danny",
age: 23,
gender: "boy"
}
return (
<div>
{/* 对象的解构赋值来传递数据 */}
<Stu {...person}></Stu>
</div>
)
}
}
4.2 class关键字创建组件---有状态组件
import React, { Component } from "react"
// 将 person 传入 Stu 组件中 --- 子组件
// 使用 props 接收传进来的参数; props 只读,不可更改
class Stu extends React.Component{
// render函数 是渲染当前组件对应的虚拟dom元素, props 接收 父组件 传递过来的值
render(props){
// 通过 this.props.*** 就可以接收数据
//返回一个jsx语法
return <h1 style={{color: '#1da57a'}}>Holle World { this.props.name } - { this.props.age} - { this.props.gender }</h1>
}
}
export default class User extends Component {
render() {
const person = {
name: "Danny",
age: 23,
gender: "boy"
}
return (
<div>
{/* 对象的解构赋值来传递数据 */}
<Stu {...person}></Stu>
</div>
)
}
}
用构造函数创建出来的组件,和用class创建出来的组件,
这两种不同的组件之间的本质区别就是:有无state属性 和 生命周期函数!
有状态组件和无状态组件之间的本质区别就是:有无state属性!
5. react的样式
5.1 渲染评论列表样式
行内样式
将
css样式写成js对象的形式
import React, { Component } from "react"
// 这是评论列表组件
export default class CommentList extends Component {
constructor(params) {
super()
this.state = {
CommentList: [
{ id: 1, user: '张三', content: '哈哈,沙发' },
{ id: 2, user: '张三2', content: '哈哈,板凳' },
{ id: 3, user: '张三3', content: '哈哈,凉席' },
{ id: 4, user: '张三4', content: '哈哈,砖头' },
{ id: 5, user: '张三5', content: '哈哈,楼下山炮' }
]
}
}
render(props){
return (
<div>
{ /* 头部的行内样式 */}
<h1 style={{ color: 'red', fontSize: '24px', backgroundColor: 'yellow', fontWeight: 700 }}>这是评论列表组件</h1>
{ this.state.CommentList.map(item => <CommentDetail key={ item.id } { ...item }></CommentDetail> )}
</div>
)
}
}
// 定义子组件的object样式
const styles = {
itemStyle: { border: '1px dashed #ddd', margin: '10px', padding: '10px', boxShadow: '0 0 10px #ddd' },
userStyle: { fontSize: '14px' },
contentStyle: { fontSize: '12px' }
}
// 子组件
function CommentDetail(props) {
console.log(props)
return (
<div style={ styles.itemStyle }>
<h1 style={ styles.userStyle }>评论人:{ props.user }</h1>
<p style={ styles.contentStyle }>评论内容:{ props.content }</p>
</div>
)
}

使用sass
第三方使用css;自己的样式使用sass
配置loader
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader']
},
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]-[local]-[hash:base64:5]',
},
}
},
{ loader: 'sass-loader' }
]
}
使用:
// .jsx 文件
// 自己的 sass 文件,需要使用 sass 配置规则解析
import cssobj from '@/css/commentList.scss'
console.log('commentList.css', cssobj) import 'bootstrap/dist/css/bootstrap.css' class CommentList extends React.Component {
constructor(params) {
super()
}
render(props){
return (
<div>
{/* 自己的 css */}
<h1 className={ [cssobj.title, 'test'].join(' ') }>这是评论列表组件</h1>.
{/* 第三方的 css */}
<button className="btn btn-primary">按钮</button>
</div>
)
}
}
6. react中的事件
模拟实现 VUE 中的双向绑定数据原理
//#region 介绍 react 中绑定事件的标准格式
import React from "react" class BindEvent extends React.Component {
constructor(params) {
super()
this.state = {
msg: '哈哈',
name: 'LiMing',
color: '#' + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, '0')
}
}
render(props){
return (
<div>
<h1>BindEvent 组件</h1>
{/* 绑定点击事件 onClick */}
<button onClick={ () => this.myclickHandler(this.state.color) }>按钮</button>
{/* 显示 state 中的数据 */}
<h3>{ this.state.msg }</h3>
{/* 模拟实现 VUE 中的双向绑定数据原理 */}
<input type="text" ref="txt" style={{ width: '100%'}} value={ this.state.msg } onChange={e => this.txtChange(e) }/>
</div>
)
}
txtChange = (e) => {
// 获取 input 中 value 的两种方法
// console.log(e.target.value === this.refs.txt.value) // true
this.setState({
msg: e.target.value // this.refs.txt.value
})
}
myclickHandler = color => {
// this.setState({}, callbcak) 是异步的,需要在 callbcak 获取最新的值
this.setState({
msg: color
},() => {
console.log( '2', this.state.msg )
})
// 还是未修改的值
console.log( '1', this.state.msg )
}
} export default BindEvent
7. react组件的生命周期函数
react组件的生命周期函数分为三个阶段组件创建阶段:
componentWillMount:组件将要被挂载,此时还没有开始渲染虚拟DOM
render:第一次开始渲染真正的虚拟DOM,当render执行完,内存中就有了完整的虚拟DOM了
componentDidMount:组件完成挂载,此时,组件已经渲染到页面上了,数据和页面达到同步,当这个方法执行完,组件进入 运行中 的状态
- 组件运行阶段
componentWillReceivrProps:组件将要接受新的属性,此时,只要这个方法被触发,就证明父组件为当前子组件传递了新的属性值
shouldComponenUpdate:组件是否需要被更新,此时,组件尚未开始更新,但是 state 和 props 中的数据是最新的
componentWillUpdate:组件将要被更新,此时尚未开始更新,内存中的虚拟DOM树还是旧的
render:此时,重新根据最新的 state 和 props 重新渲染一颗存在内存中的 虚拟DOM树,当 render 调用完毕,内存中旧的DOM树 替换 成新的 DOM树了,但是页面还是旧的
componentDidUpdate:此时,页面又被重新渲染了,state 和 虚拟DOM 页面都是最新的,并且保持同步
- 组件销毁阶段
componentDidUpdate:组件将要被卸载,此时组件还可以正常使用

使用计数器学习react的生命周期:
import React from "react"
import ReactTypes from 'prop-types' class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: 'ok',
count: props.initcount
}
} // 父组件没有传递值是,设置默认值
static defaultProps = {
initcount: 0
} // 创建静态的 propTypes 对象,可以校验 父组件传递过来的值得类型
static propTypes = {
initcount: ReactTypes.number // prop-types 指定数据类型
} // 组件将要被挂载到页面上,此时,数据已经存在,但是还没有开始渲染虚拟DOM = VUE: created
componentWillMount() {
console.log('componentWillMount 函数')
// 无法获取DOM,页面 和 虚拟DOM 还没有渲染
console.log(document.querySelector('.myh3')) // null
// props 和 state 可以获取到
console.log(this.props.initcount) //
console.log(this.state.msg) // ok
this.myselfFunc()
} // 渲染内存中的虚拟DOM,但是页面尚未真正显示DOM元素
render() {
// 每当调用 render 函数时,页面上的元素还是旧的
console.log('render 函数')
// return 之前,虚拟DOM还没有创建, return 之后,虚拟DOM创建,但是还没有挂载到页面上
return (
<div>
<h1>这是计数器组件</h1>
<input id="btn" type="button" value="+1" onClick={this.increment} />
<hr/>
<h3 ref="h3" className="myh3">当前数量为:{ this.state.count }</h3>
<h3 className="myh3">当前数量为:{ this.props.initcount }</h3>
</div>
)
} // 组件挂载到页面上,会进入这个生命周期函数,此时页面上渲染虚拟DOM了 == VUE mounted
componentDidMount() {
console.log('componentDidMount 函数')
console.log(document.querySelector('.myh3')) // <h3 ... </h3>
// 使用原生js方法,改变 count 值
// document.querySelector('#btn').onclick = () => {
// this.setState({
// count: this.state.count + 2
// })
// }
} // 从这里判断组件是否需要更新
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate 函数')
// 该周期中必须返回一个 boolean 值
// 返回 false,则不执行其他生命周期函数,但是 state 的数据会被更改
// 返回 true,继续执行其他生命周期函数
// console.log(this.state.count) // 此时直接使用this.state是未更改的值
// console.log(nextProps, nextState) // 最新的 props 和 state
// return nextState.count % 2 === 0? true: false
return true
} // 组件将要更新,此时尚未更新,在进入这个生命周期函数的时候,内存中的虚拟DOM是旧的,页面上的DOM元素也是旧的
componentWillUpdate() {
console.log('componentWillUpdate 函数')
console.log(document.querySelector('.myh3').innerText) // 旧的数据
console.log(this.refs.h3.innerText)
} // 此时虚拟DOM,页面,数据都是最新的
componentDidUpdate() {
console.log('componentDidUpdate 函数')
console.log(this.refs.h3.innerText)
}
myselfFunc() {
console.log('自己定义的函数');
} increment = () => {
this.setState({
count: this.state.count + 1
})
}
} export default Counter
使用父子组件学习componentWillReceiveProps周期函数
注意:第一次渲染子组件时,
componentWillReceiveProps不会传递props属性。
import React from "react"
class Parent extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: '父组件中的 msg 消息'
}
}
render() {
return (<div>
<h1>这是父组件</h1>
<input type="button" value="点击修改msg的值" onClick={this.changeMsg}/>
<hr/>
<Son pmsg={ this.state.msg }></Son>
</div>)
}
changeMsg = () => {
this.setState({
msg: '更改了,变成新值了'
})
}
}
class Son extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (<div>
<h3>这是子组件</h3>
<p>{ this.props.pmsg }</p>
</div>)
}
// 组件接受外界传值触发
// 子组件第一次被渲染到页面上时候,不会触发这个方法,第二次以后才会触发
componentWillReceiveProps(nextProps) {
console.log('被触发了')
// 注意:在 componentWillReceiveProps 中拿到的值是未更改的值!!
// console.log(this.props.pmsg)
console.log(this.props.pmsg + '----' + nextProps.pmsg);
}
}
export default Parent
8. react中绑定this传递参数的3中方式
import React from "react"
class BindThis extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: '这是 BindThis组件中的 msg 消息'
}
// 绑定 this 并传参的方式 ②
// bind 的返回值 是调用函数和参数的 copy
// 注意:bind 不会修改原函数的 this 指向
this.changeMsg2Copy = this.changeMsg2.bind(this, '参数one', '参数two')
}
render() {
return (<div>
<h1>这是 BindThis 组件 </h1>
{/* 方式 ① */}
{/* bind 修改函数内部的 this 指向,指向 bind 参数列表中的第一个参数 */}
<input type="button" value="react 中绑定 this 传递参数的3中方式1" onClick={ this.changeMsg1.bind(this, '参数1', '参数2')}/>
<hr />
{/* 方式 ② */}
<input type="button" value="react 中绑定 this 传递参数的3中方式2" onClick={ this.changeMsg2Copy }/>
<hr />
{/* 方式 ③ */}
<input type="button" value="react 中绑定 this 传递参数的3中方式3" onClick={ () => this.changeMsg3('参数1111', '参数2222') }/>
<h2>{ this.state.msg }</h2>
</div>)
}
changeMsg1(arg1, arg2) {
console.log(this) // 指向实例
this.setState({
msg: '变成新值了' + arg1 + arg2
})
}
changeMsg2(arg1, arg2) {
console.log(this) // undefined
this.setState({
msg: '变成新值了' + arg1 + arg2
})
}
changeMsg3 = (arg1, arg2) => {
console.log(this) // 指向实例
this.setState({
msg: '变成新值了' + arg1 + arg2
})
}
}
export default BindThis
9. context多重组件传值
import React from "react"
import ReactTypes from "prop-types"
class Conm1 extends React.Component {
constructor(params) {
super()
this.state = {
color: "red"
}
} // 1. 在父组件定义 func,这个func固定的名字 getChildContext
// 内部必须返回一个对象,这个对象就是要共给子孙组件的数据
getChildContext() {
return {
color: this.state.color
}
} // 2. 使用 属性校验,规定一下传递给子组件的数据类型,固定名字 childContextTypes
static childContextTypes = {
color: ReactTypes.string // 规定传递给子组件的数据类型
}
render(props) {
return (
<div>
<h1>这是父组件:通过 getChildContext 将父组件中的颜色 red 传递给孙子组件</h1>
<hr />
<Conm2></Conm2> </div>
)
}
} class Conm2 extends React.Component {
render(props) {
return (
<div>
<h3>这是子组件</h3>
<hr />
<Conm3></Conm3>
</div>
)
}
} class Conm3 extends React.Component {
constructor(params) {
super()
this.state = {}
}
// 3. 先来个属性校验,校验父组件传递过来的参数类型
static contextTypes = {
color: ReactTypes.string // 这里,子组件一定要校验一下父组件传递过来的 context 的数据类型
}
render(props) {
return (
<div>
<h5 style={{ color: this.context.color }}>
这是孙子组件 --- {this.context.color}
</h5>
</div>
)
}
}
export default Conm1

React 学习笔记(1) 基础语法和生命周期的更多相关文章
- Java学习笔记之---基础语法
Java学习笔记之---基础语法 一. Java中的命名规范 (一)包名 由多个单词组成时,所有字母小写(例如:onetwo) (二)类名和接口 由多个单词组成时,所有单词首字母大写(例如:OneTw ...
- React学习笔记(五)State&声明周期
React学习笔记(五) 四.State&声明周期 可以为组件添加"状态(state)".状态与属性相似,但是状态是私有的,完全受控于当前组件. 局部状态就是只能用于类(定 ...
- React学习笔记(一) 基础知识
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我. React的基 ...
- React 入门学习笔记整理(七)—— 生命周期
(1)react 生命周期 只有类组件有生命周期,函数组件没有生命周期 1.挂载阶段:这些方法会在组件实例被创建和插入DOM中时被调用: 1)constructor(props) 初始化组件的状态.绑 ...
- Hive学习笔记:基础语法
Hive基础语法 1.创建表 – 用户表 CREATE [EXTERNAL外部表] TABLE [IF NOT EXISTS 是否存在] HUserInfo ( userid int comment ...
- Java学习笔记之基础语法(顺序,条件,循环语句)
顺序结构:自上而下 条件分支选择结构: if条件语句 1,一旦某一个分支确定执行以后,其他分支就不会执行.if后面的条件必须是boolean类型 2,if 后面如果不加大括号,默认相邻的下一 ...
- iOS学习笔记(四)——iOS应用程序生命周期
开发应用程序都要了解其生命周期,开始接触android时也是从应用程序生命周期开始的,android的应用程序生命周期更多是其组件的生命周期,例如Activity.Service.今天我们接触一下iO ...
- react学习(6)——关于组件生命周期的问题
在项目开发的过程中,遇到了一个问题: 父组件请求后台数据,收到后将数据以props传给子组件,子组件根据收到数据的不同,显示不同的内容,同时,子组件自身可以根据click操作改变根据父组件的数据显示的 ...
- maven权威指南学习笔记(四)—— maven生命周期(lifecycle)
定义: 生命周期是包含在一个项目构建中的一系列有序的阶段 举个例子来说就是maven 对一个工程进行: 验证(validate) -- 编译源码(compile) -- 编译测试源码(test-com ...
随机推荐
- shell脚本中执行sql脚本(mysql为例)
1.sql脚本(t.sql) insert into test.t value ("LH",88); 2.shell脚本(a.sh 为方便说明,a.sh与t.sql在同一目 ...
- SSH和screen服务
SSH是一种能够以安全的方式提供远程登录的协议,目前远程管理的首选方式,sshd是基于SSH协议开发的一款远程管理服务程序,在Linux系统中需要部署sshd服务程序才能使用SSH协议来进行远程管理, ...
- 8核AMD Zen加持:微软Surface这回血拼
微软定于10月2日在纽约举办Surface新品发布会,几乎全线消费级产品都将更新,比如15英寸Surface Laptop 3. 最新爆料称,15寸Surface Laptop 3预计一口气推出6款型 ...
- ajax请求QQ音乐
搜索歌曲 function go() { var val = document.getElementById("name").value; ...
- C++服务器与java进行socket通信案例
分类: [java]2012-10-08 12:03 14539人阅读 评论(46) 收藏 举报 注:本代码版权所有!!!转载时请声明源地址:http://blog.csdn.net/nuptboyz ...
- ZC706+FMCOMMS5应用笔记
1.板载时钟配置. ZC706有200MHz LVDS差分时钟源SiT9102,作为ZYNQ系统参考时钟. COMMS5板子上有ADCLK846时钟Buffer分路器作为AD9361的时钟源,AD84 ...
- 吴裕雄--天生自然JAVA数据库编程:处理大数据对象
import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.SQLException ; import j ...
- Luogu P3263 [JLOI2015]有意义的字符串
Link 设\(e=\frac{b+\sqrt d}2,i=\frac{b-\sqrt d}2\). 显然\(f_n=e^n+i^n\)是一个整数,且\(f_n=(e+i)f_{n-1}+eif_{n ...
- 怎样管理Exchange Server 2013资源邮箱
1. exchange资源邮箱介绍 这次将介绍Exchange Server 2013的资源邮箱相关内容. Exchange Server 2013的资源邮箱包含两类,其一为“会议室邮箱”,另一类是“ ...
- 51nod 1765 谷歌的恐龙
一开始看到了期望吓半死..然后弱弱的写了一下式子.设∑是出去m项之后的和,∑' 是m项的和. E=(n/m)*(∑'/m)+(n/m)*((n-m)/n)*(∑'/m+∑/(n-m))+(n/m)*( ...