React基础知识点

react是三大前端主流框架之一。它有着庞大多生态体系,几乎所有开发需求都有成熟的解决方案;它上手简单,可在几小时内上手React技术,但知识很广,需要更多时间才能完全驾驭;它社区强大,使用人群多,可以很容易的找到志同道合的人一起学习

开发环境

本文使用的react版本:v16.8.6
需要确保电脑上的环境:Node >= 6 and npm >= 5.2

创建项目

npx create-react-app my-app
cd my-app
npm start

配置

// 根目录下新建  config-overrides.js
const { override, fixBabelImports, addLessLoader, addWebpackAlias, useEslintRc } = require('customize-cra')
const path = require('path')

module.exports = override(
  // 配置antd按需引入
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: true
  }),
 // 配置less
  addLessLoader({
    javascriptEnabled: true,
    modifyVars: { '@primary-color': '#1890ff' }
  }),
 // 配置别名
  addWebpackAlias({
    ['@']: path.resolve(__dirname, 'src')
  }),
  // 使用eslint
  useEslintRc()
)

JSX

JSX就是JS和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到<,JSX就当作HTML解析,遇到{就当JavaScript解析.

// 最基本的jsx
const element = <h1>Hello, world!</h1>

// 复杂的jsx
<ul className="list">
    <li>{message}</li>
	<li>{right ? 'right' : 'left'}</li>
</ul>

// React渲染到页面
ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
)

组件

React要求必须在一个组件的最外层进行包裹,如果代码中不需要多余的标签,可用React.Fragment包裹,此时打包后不会产生新标签

  • class组件
// App.js
import React, {Component} from 'react'
class App extends Component{
  render(){
       return (
           <div>
               Hello World
           </div>
       )
   }
}
export default App
  • 函数组件
const App = props => (
  <div>{props.message}</div>
)
  • 组合组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  )
}

Props和State

Props

下列函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果,这就是纯函数

function sum (a, b) {
  return a + b;
}
  • 组件无论是使用函数声明还是通过class声明,都决不能修改自身的 props
  • 所有 React 组件都必须像纯函数一样保护它们的 props 不被更改

State

  • 不要直接修改 State,应该使用setState()
  • State 的更新可能是异步的
this.setState((state, props) => ({
  counter: state.counter + props.increment
}), () => console.log('本次更新完成'))
  • State 的更新会被合并,互不影响

事件处理

  • React 事件的命名采用小驼峰式(camelCase),而不是纯小写
  • 使用JSX时需要传入一个函数作为事件处理函数,而不是一个字符串
  • 不能通过返回false的阻止默认行为,必须显式的使用preventDefault

解决this指向问题

构造函数中bind

constructor(props) {
   super(props)
   this.handleClick = this.handleClick.bind(this)
}
handleClick() {}
...
<button onClick={this.handleClick}>Hello</button>

HTML节点

handleClick() {}
<button onClick={this.handleClick.bind(this)}>Hello</button>

ES6 箭头函数

// 注意: 这是 *实验性* 语法。
handleClick = event => {
 event.preventDefault()
 // handle
}
...
<button onClick={this.handleClick}>Hello</button>
<button onClick={event => this.handleClick(event)}>Hello</button>

条件渲染和列表渲染

条件渲染

  • 通过if判断,返回不同的JSX
  • 与运算符 &&
  • 三目运算符
  • 阻止组件渲染 return null

列表渲染->通过map函数遍历数组

[1, 2].map(num => <li key={num}>{num}</li>)

在jsx中嵌入map

function NumberList(props) {
  const numbers = props.numbers
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString() value={number} />
      )}
    </ul>
  )
}

受控组件和非受控组件

受控组件: 组件绑定value,监听变化,手动更新state

handleChange = event => {
  this.setState({value: event.target.value})
}
...
<input value={this.state.value} onChange={this.handleChange} />

当需要处理多个 input 元素时,可以给每个元素添加 name 属性,并让处理函数根据 event.target.name 的值选择要执行的操作

非受控组件: react自己内部进行了处理

constructor(props) {
    super(props)
    this.handleSubmit = this.handleSubmit.bind(this)
    this.input = React.createRef()
  }

handleSubmit(event) {
    console.log(this.input.current.value)
    event.preventDefault()
  }
...
<input ref={this.input} />

指定默认值
<input type="checkbox"/><input type="radio"/> 支持 defaultChecked
<select/><textarea/><input/> 支持 defaultValue

react组件与html不同的几个点:

  • textarea在html中通过子元素定义文本,react则使用 value 属性代替
  • select默认选中,在html中需要在options标签使用selected,而在react中在select标签上使用 value 属性
  • <input type="file" /> 始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制

注意事项

  • 使用map循环时需要设置一个唯一的key,否则会报错
  • 删除列表的某一项
    let list = this.state.list
    list.splice(index, 1)
    this.setState({ list })
    
  • jsx中注释 {/* 注释 */}{ // 注释 }
  • jsx中类名要使用className而不是class
  • jsx中要标签插入html要用dangerouslySetInnerHTML属性
  • jsx中label标签要使用htmlfor而不是for

生命周期

image.png

  • 初始化默认的属性对象
static defaultProps = {
  name:'计数器'
}
  • 初始化默认的状态对象
constructor(props) {
  super(props);
  this.state = {
    number: 0
  }
}
  • componentWillMount() 废弃
  • componentDidMount
  • componentWillReceiveProps() 废弃
  • getDerivedStateFromProps() 新增
  • shouldComponentUpdate()
  • componentWillUpdate() 废弃
  • getSnapshotbeforeUpdate() 新增
  • componentDidUpdate()
  • componentWillUnmount

文章作者: 徐辉波
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 徐辉波 !
评论
 上一篇
JS AES加密解密(ECB/CBC) JS AES加密解密(ECB/CBC)
今天配合后端完成账户密码的加密和解密,使用的是AES加密算法 环境配置 js文件https://code.google.com/archive/p/crypto-js/downloads 在线AES加密解密地址http://tool
2019年05月21日
下一篇 
每日一题 每日一题
第一题: ['1', '2', '3'].map(parseInt) 解析 执行结果:[1, NaN, NaN],此题需要注意以下两点 array.map(function(currentValue,index,arr), thisV
2019年04月21日
  目录