React基础知识梳理(含案例和讲解)

React基础知识梳理(含案例和讲解)

1,react 是什么?

React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。(官方明确说react不是框架,被人称为框架,可能是他真的足够强大吧。。)

  • 声明式:为状态设计UI
  • 组件化:就是一个个“零件”(即组件), 用这些零件拼凑成需要的“成品”(即UI
  • 随时随地: 不管用什么技术栈,随时随地都可以用react编写。

点击进入 React中文官方文档

2,react能做啥?

做页面的UI交互。

3,怎么用react?
  • 方法一:在HTML的script标签引入React,好处是引入后能马上开始写react代码,不需要做其他引入了。适合新手。但是缺点是不适合大型 项目。所以不推荐。

  • 方法二:用react的脚手架: create-react-app

    ​ 分两种安装方法:

    • npm install -g create-react-app //安装react脚手架

      create-react-app 文件名 //创建react文件

      cd 文件名 //进入react文件

      npm start //启动项目

    • 官方文档推荐方法npx create-react-app 文件名
      cd 文件名
      npm start

4,上面的脚手架都装了啥玩意儿?

先来看看react文件里都有啥→
React基础知识梳理(含案例和讲解)_第1张图片

逐个说明:

  • node_modules文件夹:学过node都知道,这是存放node下载模块的,我们下载的node模块都存到这里面了
  • public文件夹:这是存放了公共资源的文件夹。html主页模板,logo图标等等.
  • src文件夹:存放自己写的代码等一些静态资源。js,css,img等。
    需要注意的是,index.js是默认的要渲染的文件。也就是说,当用npm start启动项目时,就会启动index.js里面的内容了。
5,代码写好了,该怎么让别人都能登陆浏览我编写的网站呢?

打包项目 npm run build 把开发环境中写好的代码,转成生产环境,生成一个build文件夹。把这个文件夹的内容,放到服务器根目录,网站就可以让别人看到了。

6,怎么开始写react代码呢?

还记得存放我们自己写的代码的文件夹吗? 没错,就是src文件夹

进入该文件夹。找到默认渲染的index.js文件,用编辑器打开。

把里面的ReactDOM.render(...)的这一段代码,改写成下面这样:

ReactDOM.render(
  

Hello World!

, document.getElementById('root') );

然后在创建的react文件夹里,打开cmd控制台,输入 npm start

就会自动进入到http://localhost:3000/,页面中渲染出了这样的内容:
React基础知识梳理(含案例和讲解)_第2张图片
第一段react代码,就写成了!!!

7,JSX简介

什么是JSX???

再回头看一下上面的代码,

Hello World!

,

是不是很奇怪?JS里面怎么有HTML标签?!

没错,JS里面可以写HTML标签,这种形式,就是JSX了。

JSX既不是字符串,也不是HTML。它就是一种JS里面写HTML标签的语法。

这里还可以这样赋值。const element =

Hello World!

在JSX里,还可以用{ } ,声明变量或者引入表达式。{ }里可以放任何JS表达式。

比如

hello, 张{1 + 2}

,输出结果就是hello, 张3

还可以这样,const name = '张三'

hello {name}

输出结果就是hello 张三

注意:JSX里的class类属性,要写成className

看完这些,肯定还是对JSX一脸懵逼的。

但是不用着急,后续还会用到大量的JSX,用多了,肯定会爱不释手的!

8,元素渲染

元素,是构成React应用的最小单位。

元素,描述了你在屏幕上想看到的内容

比如 const element =

Hello, World!

这就是要给元素,Hello, World!就是通过ReactDOM在页面上要渲染出来的内容了。

想要渲染出元素内容,只需要把元素放入ReactDOM.render()里即可。

ReactDOM.render(
  

Hello World!

, //这里就是要渲染的元素 //注意,这里的逗号,别忘了!!! document.getElementById('root') );

元素,是不可变的普通对象。它代表了某个特定时刻的UI

9,组件

组件,类似于JS函数。但是组件的函数名首字母要大写。(小写就是函数,大写就是组件)

组件,是一块独立的代码。需要时,直接调用渲染即可。

组件,有两种标准写法:

第一种,函数形式的,例如:

function Welcome() {
    return (
    	

Hello world!

) } ReactDOM.render( , document.getElementById('root') )

第二种,类形式的,例如:

class Welcome extends React.Component {
    render() {
        return (
        	

Hello World!

) } } ReactDOM.render( , document.getElementById('root') )

以上两种写法,是等效的。

两个例子,是两种标准格式。也就是说,不管你要用哪个形式,要渲染什么内容,这个写法都不会变的。

注意,组件的 函数名和类名 的首字母要大写

10,带参数(props)的组件

组件里可以携带参数,但是组件的参数是唯一的,即props

在组件里用参数,就用props。 别无选择。

先说函数组件的设置参数和传递参数,举个例子

function Welcome(props) {
    return 

Hello, {props.name}

} const name = '迪丽热巴!' ReactDOM.render( , document.getElementById('root') ) 输出结果: Hello, 迪丽热巴!

这个name 通过组件的name={name}赋值, 传给了props参数。

这里,我们打印一下props,看下props里面有什么。

function Welcome(props) {
    console.log(props)
    return 

Hello, {props.name}

} const name = '迪丽热巴!'

打印结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfxWVU7C-1595528626313)(C:\Users\Shinelon\AppData\Roaming\Typora\typora-user-images\image-20200721103637339.png)]

结果显示,props是一个对象,对象里有属性name。就是下面这样:

props = {
     
    name: '迪丽热巴'
}

也就是说,通过 语句, name的值以对象的形式传给了props。

类组件的参数及传递

先看个例子:****

class Welcome extends React.Component {
  render() {
    console.log(this.props)
    return 

Hello, {this.props.name}

} } const name = '迪丽热巴' ReactDOM.render( , document.getElementById('root') )
输出结果:
Hello, 迪丽热巴

这里的this.props = {
    name: '迪丽热巴'
}

通过例子可以看出,两种组件都有同样的传递参数的形式。

值得注意的是:在调用props参数的时候,函数组件是props.name,而类组件是this.props.name 。类组件是有this的。

而且,props是只读的,不可以被修改的。所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

11,组合组件

顾名思义,就是可以把多个组件组合在一起,然后渲染出结果。

直白点说,就是把多个组件,放在一个顶层组件里,然后对顶层组件进行渲染。

举个例子:

function Welcome(props) {
return 

Hello, {props.name}

} function Name() { //顶层组件 return (
//注意,这些组件都必须包含在一个顶层标签里,不然会报错 //组件1 //组件2 //组件3 //组件4
) } ReactDOM.render( , document.getElementById('root') ) 输出结果: Hello, 迪丽热巴! Hello, 古力娜扎! Hello, 巴拉巴拉! Hello, 奥利给啊!
12,State

本篇开头提到了React的声明特性,就是为状态写UI。这个状态,就是state。

比如,人在站立的时候是一种站立状态,人在蹲下的时候,就是一种蹲下的状态。

我现在看时钟是1点钟是一种状态,一个小时后,看时钟是2点钟又是一种状态。

状态,就是处于某一点或某一时刻的数据。

举个例子:

function Clock(props) {
  return (
    

现在的时间是: {props.date.toLocaleString()}

) } ReactDOM.render( , document.getElementById('root') ) 输出结果: 现在的时间是: 2020/7/21 下午2:10:53 如果刷新页面,这个时间会随时变化。这个变化,也就是状态的变化。

如果要在代码中显示出state,就需要用到类组件了。

注意:construtor里面是唯一可以初始化状态的地方。

class Clock extends React.Component {
  constructor(props) {
    super(props) 
    this.state = { //这里是设置状态,给状态做初始化
      date: new Date()
    }
  }
  render() {
    return (
    

现在的时间是: {this.state.date.toLocaleString()}

) } } ReactDOM.render( , document.getElementById('root') ) 输出结果也是这个状态的时间,刷新页面,时间就会变化,也就是状态也在变化。
13,设置状态 setState()

​ 元素从一个状态,到另外一个状态,要怎么调整呢?

状态,是不能直接修改的。

但是,状态可以通过setState()来设置为新的状态。

setState()要放在函数中

class Clock extends React.Component {
  constructor(props) {
    super(props) 
    this.state = {
      date: new Date().toLocaleString()
    }
  }
  change = () => { //这里用来改变时间状态
    this.setState({
      date: new Date().toLocaleString()
    })
  }
  render() {
    return (
    

现在的时间是: {this.state.date}

) } } ReactDOM.render( , document.getElementById('root') )

现在,状态已经改变了。但是页面还没有自动跟着改变状态。

那么,怎么让状态自动从一个状态到另一个状态呢?

14,生命周期–从一个状态到另一个状态,只改变状态部分,不重新渲染整个组件

假如我们不需要刷新页面,就可以从一个状态调整到另一个状态

那就要用到定时器了。但是我们又希望 在用定时器的时候,能让定时器只改变时间状态,

而不是让整个组件都重新加载

那么 我们就要用到生命周期了。

我们把13条中的代码修改一下:

class Clock extends React.Component {
  constructor(props) {
    super(props) 
    this.state = {
      date: new Date().toLocaleString()
    }
  }
  componentDidMount() { //挂载计时器
    this.timer = setInterval(this.change, 1000)
  }
  componentWillUnmount() { //卸载计时器
    clearInterval(this.timer)
  }
  change = () => { //设置状态
    this.setState({
      date: new Date().toLocaleString()
    })
  }
  render() {
    return (
    

现在的时间是: {this.state.date}

//被渲染的元素 ) } } ReactDOM.render( , document.getElementById('root') )

挂载当前状态 → 卸载改变后的状态 ,这就是一个生命周期。

15,事件处理

React元素的事件处理和DOM元素的很相似,但是语法上有点不同:

  • React事件命名用驼峰命名,而不是纯小写
  • 使用JSX语法时,传入的是一个函数作为事件处理函数,而不是传入一个字符串

例如,传统的HTML:


在React中略微不同:


  • 阻止默认行为,也有所不同。
    传统的HTML阻止链接默认打开一个新页面:

    
    	Click me
    
    

    在React可能是这样的:

    handleClick = (e) => {
        e.preventDefault()
        console.log('The link was clicked.')
    }
    

事件处理案例:点击按钮 在ON和OFF之间来回切换

class ToggleBtn extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      isChanging: true
    }
  }
  handleClick = () => { // 这里如果不用箭头函数,就在constructor里绑定this
    this.setState({
      isChanging: !this.state.isChanging //修改状态
    })
  }
  render() {
    return (
      
    )
  }
}
ReactDOM.render(
  , //渲染这个组件
  document.getElementById('root')
)

16,条件渲染

在React中,你可以创建不同的组件来封装各种你需要的行为。然后,依据应用的不同状态,你可以只渲染对应状态下的部分内容

使用条件语句 if ,条件运算符(也叫三元运算符), &&, || ,!等。

举例,根据不同条件,来让组件1或者组件2来运行:

function Com1() { // 组件1
  return (
    

这是组件1在执行--

) } function Com2() { // 组件2 return (

这是组件2在执行--

) } function Run(props) { const isRunning = props.isRunning // 定义变量 if (isRunning) { //判断条件 return } return } ReactDOM.render( , document.getElementById('root') )
17,列表&&key

这里说的列表,是根据数组元素,生成相应的列表标签。

map()函数来完成

使用{}在JSX里构建一个元素集合

举例:

const numbers = [1, 2, 3, 4, 5] //给出一个数组
const listItems = numbers.map( //用map()函数对数组内每个元素进行遍历
  (number) => 
  • {number}
  • //把遍历的元素放入li标签 ) ReactDOM.render(
      {listItems}
    , //渲染时 把li标签放入ul标签 document.getElementById('root') )

    输出结果:
    React基础知识梳理(含案例和讲解)_第3张图片
    在运行这段代码时,会看到一串警告:
    React基础知识梳理(含案例和讲解)_第4张图片
    意思是,在列表里的每一个子元素都必须有一个key参数。

    怎么给子元素设置key参数呢?如下:

    const listItems = numbers.map((number) =>
        
  • //在这里给子元素设置key参数 {number}
  • )
    18,关于key参数

    key是用来帮助react识别是哪些元素改变了,比如被添加了或者被删除了。

    key是这个元素在列表中拥有独一无二的字符串

    应该在哪里设置key值呢?

    记住:在 map() 方法中的元素需要设置 key 属性

    key会传递信息给react,但是不会传递给你写的组件。

    19,表单(input, textarea, select)–受控组件

    表单有输入和提交的状态,状态保存在state属性中,state成为唯一数据源。

    渲染表单的React组件还控制着用户输入过程中表单发生的操作。被React以这种方式控制取值的表单输入元素就叫做“受控组件

    案例:提交输入的内容,并弹窗提示提交了什么内容

    class InputCom extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          value: ''
        }
      }
      handleChange=(e)=> {
        this.setState({
          value: e.target.value //输入的内容
        })
      }
      handleSubmit=(e)=> {
        alert('提交的内容是: ' + this.state.value)
        // e.preventDefault() //阻止提交刷新页面
      }
      render() {
        return (
          
    {/*提交事件*/}
    ) } } ReactDOM.render( , document.getElementById('root') )

    试运行结果:
    React基础知识梳理(含案例和讲解)_第5张图片
    input, textarea, select三者非常类似。

    值得一提的是,select中的selected属性。 在React中 并不会使用selected属性,而是在根select标签上使用value属性。

    20,表单(input type=“file”)–非受控组件

    既然有受控组件,那就一定有对应的非受控组件。

    这里先挖个坑,后续写项目用到了,回来补。

    21,状态提升

    通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。这就叫“状态提升

    个人觉得官方文档中给的案例看着有点费劲儿,就自己写了一个长度间的转换案例,如下:

    let dataTitle = {
      m: '输入米数: ',
      cm: '输入厘米数: '
    }
    
    //抽离出来的输入框组件
    class LengthData extends React.Component {
      render() {
        let title = this.props.title
        let input = this.props.input
        let onChange = this.props.onChange
        let data = this.props.data
        return (
          
    {title}
    ) } } //编写实现输入框的组件 class Length extends React.Component { constructor(props) { super(props) //状态提升 this.state = { type: '', input: '' } } checkedInput(input) { // console.log(typeof(input)) if (Number.isNaN(input) || parseFloat(input) < 0) { alert ('输入数据有误,重新输入!') this.setState({ type: '', input: '' }) } return input } convertCM(input) { return input * 100 } convertM(input) { return input / 100 } handleChange=(type, e) => { if (type === 'meter') { this.setState({ type: 'meter', input: e.target.value }) }else if (type === 'centimeter') { this.setState({ type: 'centimeter', input: e.target.value }) } } render() { //meter centimeter type data 这些都是为实现交互而设置的变量 let input = this.state.input let type = this.state.type let meter = type === 'centimeter' ? this.convertM(this.checkedInput(input)) : input let centimeter = type === 'meter' ? this.convertCM(this.checkedInput(input)) : input return (

    长度单位转换

    {this.handleChange('meter' ,e)}} /> {this.handleChange('centimeter' ,e)}} />
    ) } } ReactDOM.render( , document.getElementById('root') )

    **第一步:**编写实现输入框的组件(这一步在代码案例中看着不是很明显了)

    **第二步:**抽离输入框组件(方便写入多个输入框)

    **第三步:**状态提升(把子组件中的状态拿走,状态都放在父组件中)

    **第四步:**状态交互 (核心代码,也是最难理解的一段代码)

    **第五步:**调试bug(输入和输出结果的调试,比如输入不符合要求,给错误提示,然后清空输入框,阻止交互)

    22,组合与继承的对比

    官方文档说明:巧用组合,慎用继承

    组合在实际敲代码的过程中,非常容易用到,且我们在学习的过程中,已经用过多次。

    举例说明:

    function App1() {
      return (
        

    Hello, React!

    ) } function App2() { return (

    你好,react!

    ) } function App3() { return (

    翻译如下:

    ) } ReactDOM.render( , document.getElementById('root') ) // 该案例就是把通过App3 把组件App1和App2组合在一起,通过render渲染出来。

    输出结果:
    React基础知识梳理(含案例和讲解)_第6张图片

    23, Thinking In React
    • 用react思想构建快速响应的大型web应用程序。

    • 写网页时,最好先写静态页面,再写交互UI。两者分开写。

    • 因为静态页面代码多,细节少。 交互UI是代码少,细节多。(参照第21条给出的案例)

    • React是基于state的改变来实现UI交互的。所以,用好state。

    • 习惯写组件,避免重复代码。

    • 用props和state不止可以从父组件到子组件传输数据,还可以实现从子组件到父组件的数据传输。

    看来了这里,恭喜你,你已经是React的基础用户了!

    赶紧写个项目练练手吧!

    后续我会把React的进阶知识整理出来,发到博客。

    -----------------------------End-------------------------------
    

    你可能感兴趣的:(react,reactjs)