ReactJs学习
2019-12-04 09:42:00 0 举报
AI智能生成
react学习笔记
作者其他创作
大纲/内容
基本环节安装
使用 React.js 官网所推荐使用的工具 create-react-app 工具。它可以帮助我们一键生成所需要的工程目录,并帮我们做好各种配置和依赖,也帮我们隐藏了这些配置的细节。也就是所谓的“开箱即用”。
https://github.com/facebookincubator/create-react-app
使用 create-react-app 初始化项目
npm install -g create-react-app
create-react-app <项目名>
cd <项目名>
npm start
使用JSX描述UI信息
import React,{Component} from 'react'
import ReactDOM from 'react-dom'
import './index.css'
class Header extends Component{
render() {
return (
<div>
<h1>React 小书</h1>
</div>
)
}
}
ReactDOM.render(
<Header/>,
document.getElementById("root")
)
function renderContent(content) {
ReactDOM.render(
<h1>{content}</h1>,
document.getElementById("root")
)
}
//renderContent("hello world");
import ReactDOM from 'react-dom'
import './index.css'
class Header extends Component{
render() {
return (
<div>
<h1>React 小书</h1>
</div>
)
}
}
ReactDOM.render(
<Header/>,
document.getElementById("root")
)
function renderContent(content) {
ReactDOM.render(
<h1>{content}</h1>,
document.getElementById("root")
)
}
//renderContent("hello world");
组件的render方法
在React.js中一切皆组件,在编写React.js组件时,一般要继承React.js的Component
import React,{Component} from 'react'
一个组件类必须要实现一个render方法
必须使用一个外层的 JSX 元素把所有内容包裹起来
表达式插入
当 JSX 当中 插入JavaScript的表达式,表达式返回的结果相应地渲染到页面上,表达式使用 { } 包裹
render() {
const name = '小书'
const className = 'header'
return (
<div className={className}>
<h1>React {name} {1+2}</h1>
</div>
)
}
const name = '小书'
const className = 'header'
return (
<div className={className}>
<h1>React {name} {1+2}</h1>
</div>
)
}
因为 class 是 JavaScript 的关键字,所以 React.js 中定义了一种新的方式:className 来帮助我们给元素添加类名
for 属性,例如 <label for='male'>Male</label>,因为 for 也是 JavaScript 的关键字,所以在 JSX 用 htmlFor 替代,即 <label htmlFor='male'>Male</label>。
而其他的 HTML 属性例如 style 、data-* 等就可以像普通的 HTML 属性那样直接添加上去。
条件返回
render () {
const isGoodWord = true
return (
<div>
<h1>
React 小书
{isGoodWord
? <strong> is good</strong>
: null
}
</h1>
</div>
)
}
const isGoodWord = true
return (
<div>
<h1>
React 小书
{isGoodWord
? <strong> is good</strong>
: null
}
</h1>
</div>
)
}
必须使用一个外层的 JSX 元素把所有内容包裹起来
组件的 state 和 setState
一个组件的显示形态是可以由它数据状态和配置参数决定的
React.js 的 state 就是用来存储这种可变化的状态的。
class LikeButton extends Component {
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? '取消' : '点赞👍'}
</button>
)
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? '取消' : '点赞👍'}
</button>
)
}
}
setState接受对象参数
setState 方法由父类 Component 所提供。当我们调用这个函数的时候,React.js 会更新组件的状态 state ,并且重新调用 render 方法,然后再把 render 方法所渲染的最新的内容显示到页面上
一定要使用 React.js 提供的 setState 方法,它接受一个对象或者函数作为参数。
传入一个对象的时候,这个对象表示该组件的新状态。但你只需要传入需要更新的部分就可以了,而不需要传入整个对象。
constructor (props) {
super(props)
this.state = {
name: 'Tomy',
isLiked: false
}
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
...
super(props)
this.state = {
name: 'Tomy',
isLiked: false
}
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
...
因为点击的时候我们并不需要修改 name,所以只需要传入 isLiked 就行了。Tomy 还是那个 Tomy,而 isLiked 已经不是那个 isLiked 了
setState 接受函数参数
调用 setState 的时候,React.js 并不会马上修改 state。而是把这个对象放到一个更新队列里面,稍后才会从队列当中把新的状态提取出来合并到 state 当中,然后再触发组件更新
这里就自然地引出了 setState 的第二种使用方式,可以接受一个函数作为参数。React.js 会把上一个 setState 的结果传入这个函数,你就可以使用该结果进行运算、操作,然后返回一个对象作为更新 state 的对象
handleClickOnLikeButton () {
this.setState((prevState) => {
return { count: 0 }
})
this.setState((prevState) => {
return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
})
// 最后的结果是 this.state.count 为 3
}
this.setState((prevState) => {
return { count: 0 }
})
this.setState((prevState) => {
return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
})
// 最后的结果是 this.state.count 为 3
}
这样就可以达到上述的利用上一次 setState 结果进行运算的效果
setState合并
进行了三次 setState,但是实际上组件只会重新渲染一次,而不是三次
React.js 内部会把 JavaScript 事件循环中的消息队列的同一个消息中的 setState 都进行合并以后再重新渲染组件
配置组件的props
组件是相互独立、可复用的单元,一个组件可能在不同地方被用到。但是在不同的场景下对这个组件的需求可能会根据情况有所不同
React.js 的 props 就可以帮助我们达到这个效果。每个组件都可以接受一个 props 参数,它是一个对象,包含了所有你对这个组件的配置
在使用一个组件的时候,可以把参数放在标签的属性当中,所有的属性都会作为 props 对象的键值:
class LikeButton extends Component {
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
const likedText = this.props.likedText || '取消'
const unlikedText = this.props.unlikedText || '点赞'
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? likedText : unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton likedText="已赞" unlikedText="赞" />
</div>
)
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
const likedText = this.props.likedText || '取消'
const unlikedText = this.props.unlikedText || '点赞'
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? likedText : unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton likedText="已赞" unlikedText="赞" />
</div>
)
}
}
JSX 的表达式插入可以在标签属性上使用。所以其实可以把任何类型的数据作为组件的参数,包括字符串、数字、对象、数组、甚至是函数等等
JSX 的 {} 内可以嵌入任何表达式,{{}} 就是在 {} 内部用对象字面量返回一个对象而已。
class LikeButton extends Component {
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
const wording = this.props.wordings || {
likedText:'取消',
unlikedText:'点赞'
}
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? wording.likedText : wording.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton wording={{likedText:'已赞',unlikedText:'赞'}} />
</div>
)
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
const wording = this.props.wordings || {
likedText:'取消',
unlikedText:'点赞'
}
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? wording.likedText : wording.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton wording={{likedText:'已赞',unlikedText:'赞'}} />
</div>
)
}
}
往组件内部传入函数作为参数
class LikeButton extends Component {
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
const wording = this.props.wordings || {
likedText:'取消',
unlikedText:'点赞'
}
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? wording.likedText : wording.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton wording={{likedText:'已赞',unlikedText:'赞'}}
onClick={() => console.log("click the button")}/>
</div>
)
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
const wording = this.props.wordings || {
likedText:'取消',
unlikedText:'点赞'
}
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? wording.likedText : wording.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton wording={{likedText:'已赞',unlikedText:'赞'}}
onClick={() => console.log("click the button")}/>
</div>
)
}
}
默认配置defaultProps
React.js 也提供了一种方式 defaultProps,可以方便的做到默认配置。
class LikeButton extends Component {
static defaultProps = {
wordings:{
likedText:'取消',
unlikedText:'点赞'
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? this.props.wordings.likedText : this.props.wordings.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton
onClick={() => console.log("click the button")}/>
</div>
)
}
}
static defaultProps = {
wordings:{
likedText:'取消',
unlikedText:'点赞'
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? this.props.wordings.likedText : this.props.wordings.unlikedText}
</button>
)
}
}
class Index extends Component {
render () {
return (
<div>
<LikeButton
onClick={() => console.log("click the button")}/>
</div>
)
}
}
props不可变
props 一旦传入进来就不能改变
React.js 希望一个组件在输入确定的 props 的时候,能够输出确定的 UI 显示形态。如果 props 渲染过程中可以被修改,那么就会导致这个组件显示形态和行为变得不可预测,这样会可能会给组件使用者带来困惑。
组件的使用者可以主动地通过重新渲染的方式把新的 props 传入组件当中,这样这个组件中由 props 决定的显示形态也会得到相应的改变。
class LikeButton extends Component {
static defaultProps = {
wordings:{
likedText:'取消',
unlikedText:'点赞'
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked,
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? this.props.wordings.likedText : this.props.wordings.unlikedText}
</button>
)
}
}
class Index extends Component {
constructor () {
super()
this.state = {
likedText:'已赞',
unlikedText:'赞'
}
}
handleClickOnChange () {
this.setState({
likedText:'取消',
unlikedText:'点赞'
})
}
render () {
return (
<div>
<LikeButton
wordings={{
likedText:this.state.likedText,
unlikedText:this.state.unlikedText
}
}
/>
<div>
<button onClick={this.handleClickOnChange.bind(this)}>
修改 wordings
</button>
</div>
</div>
)
}
}
static defaultProps = {
wordings:{
likedText:'取消',
unlikedText:'点赞'
}
}
constructor () {
super()
this.state = { isLiked: false }
}
handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked,
})
if(this.props.onClick) {
this.props.onClick()
}
}
render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked ? this.props.wordings.likedText : this.props.wordings.unlikedText}
</button>
)
}
}
class Index extends Component {
constructor () {
super()
this.state = {
likedText:'已赞',
unlikedText:'赞'
}
}
handleClickOnChange () {
this.setState({
likedText:'取消',
unlikedText:'点赞'
})
}
render () {
return (
<div>
<LikeButton
wordings={{
likedText:this.state.likedText,
unlikedText:this.state.unlikedText
}
}
/>
<div>
<button onClick={this.handleClickOnChange.bind(this)}>
修改 wordings
</button>
</div>
</div>
)
}
}
state vs props
state
state 的主要作用是用于组件保存、控制、修改自己的可变状态。
state 在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改
state 中状态可以通过 this.setState 方法进行更新,setState 会导致组件的重新渲染。
props
让使用该组件的父组件可以传入参数来配置该组件
外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props,否则组件的 props 永远保持不变。
state 是让组件控制自己的状态,props 是让外部对组件自己进行配置。
组件的组合、嵌套和组件树
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Title extends Component {
render () {
return (
<h1>React 小书</h1>
)
}
}
class Header extends Component {
render () {
return (
<div>
<Title />
<h2>This is Header</h2>
</div>
)
}
}
class Main extends Component {
render () {
return (
<div>
<h2>This is main content</h2>
</div>
)
}
}
class Footer extends Component {
render () {
return (
<div>
<h2>This is footer</h2>
</div>
)
}
}
class Index extends Component {
render () {
return (
<div>
<Header />
<Main />
<Footer />
</div>
)
}
}
ReactDOM.render(
<Index />,
document.getElementById('root')
)
import ReactDOM from 'react-dom';
class Title extends Component {
render () {
return (
<h1>React 小书</h1>
)
}
}
class Header extends Component {
render () {
return (
<div>
<Title />
<h2>This is Header</h2>
</div>
)
}
}
class Main extends Component {
render () {
return (
<div>
<h2>This is main content</h2>
</div>
)
}
}
class Footer extends Component {
render () {
return (
<div>
<h2>This is footer</h2>
</div>
)
}
}
class Index extends Component {
render () {
return (
<div>
<Header />
<Main />
<Footer />
</div>
)
}
}
ReactDOM.render(
<Index />,
document.getElementById('root')
)
事件监听
class Header extends Component{
handleClickOnTitle () {
console.log("Click on title " + (new Date().getTime()));
}
render() {
const name = "小书";
return (
<h1 onClick={this.handleClickOnTitle}>React {name} {1!=2?<strong> 1 不等于 2</strong>:null}</h1>
)
}
}
handleClickOnTitle () {
console.log("Click on title " + (new Date().getTime()));
}
render() {
const name = "小书";
return (
<h1 onClick={this.handleClickOnTitle}>React {name} {1!=2?<strong> 1 不等于 2</strong>:null}</h1>
)
}
}
只需要给 h1 标签加上 onClick 的事件,onClick 紧跟着是一个表达式插入,这个表达式返回一个 Title 自己的一个实例方法。
在 React.js 不需要手动调用浏览器原生的 addEventListener 进行事件监听。React.js 帮我们封装好了一系列的 on* 的属性,当你需要为某个元素监听某个事件的时候,只需要简单地给它加上 on* 就可以了。而且你不需要考虑不同浏览器兼容性的问题,React.js 都帮我们封装好这些细节了。
React.js 封装了不同类型的事件,
文档地址
https://reactjs.org/docs/events.html#supported-events
这些事件属性名都必须要用驼峰命名法
没有经过特殊处理的话,这些 on* 的事件监听只能用在普通的 HTML 的标签上,而不能用在组件标签上。
event对象
React.js 将浏览器原生的 event 对象封装了一下,对外提供统一的 API 和属性,这样你就不用考虑不同浏览器的兼容性问题。
事件中的this
一般在某个类的实例方法里面的 this 指的是这个实例本身。但是你在上面的 handleClickOnTitle 中把 this 打印出来,你会看到 this 是 null 或者 undefined。
如果你想在事件函数当中使用当前的实例,你需要手动地将实例方法 bind 到当前实例上再传入给 React.js
<h1 onClick={this.handleClickOnTitle.bind(this)}>React 小书</h1>
bind的时候可以给事件监听函数传入一些参数
JSX 元素变量
renderGoodWord (goodWord, badWord) {
const isGoodWord = true
return isGoodWord ? goodWord : badWord
}
render () {
return (
<div>
<h1>
React 小书
{this.renderGoodWord(
<strong> is good</strong>,
<span> is not good</span>
)}
</h1>
</div>
)
}
const isGoodWord = true
return isGoodWord ? goodWord : badWord
}
render () {
return (
<div>
<h1>
React 小书
{this.renderGoodWord(
<strong> is good</strong>,
<span> is not good</span>
)}
</h1>
</div>
)
}

收藏

收藏
0 条评论
下一页