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