01_初入react_react学习笔记

文章目录

JSX

1.简介
  • 全称: JavaScript XML
  • react定义的一种类似于XML的JS扩展语法: XML+JS
作用
  • 用来创建react虚拟DOM(元素)对象

    a. var ele = <h1>Hello JSX!</h1>

    b. 注意1: 它不是字符串, 也不是HTML/XML标签

    c. 注意2: 它最终产生的就是一个JS对象

    d. 标签名任意: HTML标签或其它标签

    e. 标签属性任意: HTML标签属性或其它

基本语法规则

a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析

b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含

babel.js的作用

a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行

b. 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理

2.创建虚拟DOM

前置

  <div id="test1"></div>
  <div id="test2"></div>
  <script type="text/javascript" src="../js/react.development.js"></script>
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <script type="text/javascript" src="../js/babel.min.js"></script>
1.纯JS(一般不用)

var element = React.createElement(‘h1’, {id:‘myTitle’},‘hello’)

<script type="text/javascript">
    // 1. 创建虚拟DOM
    /*方式一: 纯JS(一般不用)创建虚拟DOM元素对象*/
    const msg = 'I Like You!'
    const myId = 'Atguigu'
    const vDOM1 = React.createElement('h2', {id: myId}, msg.toUpperCase())//msg转为大写
    // 2. 渲染到真实页面
    const domContainer = document.getElementById('test1')
    // debugger
    ReactDOM.render(vDOM1, domContainer)
 </script>
2.JSX创建

<h1 id=‘myTitle’>{title}</h1>

<script type="text/babel">
  // 1. 创建虚拟DOM
  /*方式二: JSX创建虚拟DOM元素对象*/
  const vDOM2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>
  // debugger
  // 2. 渲染到真实页面
  ReactDOM.render(vDOM2, document.getElementById('test2'))
</script>
3.debugger

在代码中写debugger可以起到断点作用进行调试

4.真实DOM和虚拟DOM
//虚拟dom
const vDOM1 = React.createElement('h2', {id: myId}, msg)
//真实dom
cponst rDOM1 = document.getElementById('test1')

前者比较轻,后者比较重,一旦修改页面刷新,前者只有重新渲染的时候才刷新

真实dom属性比虚拟dom多

虚拟DOM对象最终都会被React转换为真实的DOM

我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面

5. 渲染虚拟DOM(元素)
  1. 语法: ReactDOM.render(virtualDOM, containerDOM)

  2. 作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示

  3. 参数说明

a. 参数一: 纯js或jsx创建的虚拟dom对象

b. 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)

exercise:动态展示列表数据(数据数组–>标签数组)

技术点:
1). 使用JSX创建虚拟DOM
2). React能自动遍历显示数组中所有的元素
3). array.map()的使用

<body>
  <h2>前端JS框架列表</h2>
  <div id="example1"></div>
  <div id="example2"></div>

  <script type="text/javascript" src="../js/react.development.js"></script>
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <script type="text/javascript" src="../js/babel.min.js"></script>
</body>
<script type="text/babel">
    /*
     功能: 动态展示列表数据
     */

    // 数据的数组
    var names = ['jquery', 'zeptoo', 'angular', 'react全家桶', 'vue全家桶']

    // 数据的数组-->标签的数组
    //方法1
    var lis = []
    names.forEach((name, index) => lis.push(<li key={index}>{name}</li>))
    // 创建虚拟DOM
    const ul = <ul>{lis}</ul>
    // 渲染虚拟DOM
    ReactDOM.render(ul, document.getElementById('example1'))
    //方法2
    const ul2 = <ul>{
      names.map((name, index) => <li key={index}>{name}</li>)
    }</ul>
    ReactDOM.render(ul2, document.getElementById('example2'))
</script>
js新函数map()

map() 方法返回一个数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 方法按照原始数组元素顺序依次处理元素。

注意: map() 不会对空数组进行检测。

注意: map() 不会改变原始数组

var array1 = [1, 4, 9, 16];
 
const map1 = array1.map(x => {
    if (x == 4) {
        return x * 2;
    }
    return x;
});

这里注意箭头函数有两种格式:
1.只包含一个表达式,这时花括号和return都省略了。
2.包含多条语句,这时花括号和return都不能省略。

js新函数onblur

onblur 事件会在对象失去焦点时发生。

<html>
<head>
<script type="text/javascript">
function upperCase()
{
var x=document.getElementById("fname").value
document.getElementById("fname").value=x.toUpperCase()
}
</script>
</head>

<body>

输入您的姓名:
<input type="text" id="fname" onblur="upperCase()" />

</body>
</html

面向组件编程

1.步骤
<div id="example1"></div>
<div id="example2"></div>
1.定义组件
  • 工厂函数组件(简单组件,没有状态的组件)直接调用方法 有state就不能用工厂模式
function MyComponent () {
  return <h2>工厂函数组件(简单组件)</h2>
}
  • ES6组件(复杂组件)先创建实例,实例调用render方法
class MyComponent2 extends React.Component {
  render () {
    console.log(this) // MyComponent2的实例对象
    return <h2>ES6类组件(复杂组件)</h2>
  }
2.渲染组件标签
    ReactDOM.render(<MyComponent />, document.getElementById('example1'))
    ReactDOM.render(<MyComponent2 />, document.getElementById('example2'))
3.注意
  1. 组件名必须首字母大写

  2. 虚拟DOM元素只能有一个根元素

  3. 虚拟DOM元素必须有结束标签

4.ReactDOM.render()渲染组件标签的基本流程
  • React内部会创建组件实例对象/调用组件函数, 得到虚拟DOM对象
  • 将虚拟DOM并解析为真实DOM
  • 插入到指定的页面元素内部
2.组件三大属性
2.1 state
理解
  1. state是组件对象最重要的属性, 值是对象(可以包含多个数据)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

编码操作
  1. 初始化状态:
 constructor (props) {
  super(props)
  this.state = {
   stateProp1 : value1,
   stateProp2 : value2
  }
 }
  1. 读取某个状态值
 this.state.statePropertyName
  1. 更新状态---->组件界面更新
 this.setState({
  stateProp1 : value1,
  stateProp2 : value2
 })

例子:

<script type="text/babel">
  /*
  需求: 自定义组件, 功能说明如下
    1. 显示h2标题, 初始文本为: 你喜欢我
    2. 点击标题更新为: 我喜欢你
  */
  class Like extends React.Component{

    constructor(props) {
      super(props);
      //初始化状态
      this.state={
          isLikeMe:false
      }
      //将新增方法的this绑定为组件对象
      //bind返回一个新函数,因此要将新函数指向handleclick()
      this.handleClick = this.handleClick.bind(this)
    }
    //新增类方法,this默认是undefined
    handleClick(){
      //读取状态并取反
      const isLikeMe = !this.state.isLikeMe
      //更新状态
      this.setState({isLikeMe:isLikeMe})
    }

    render(){
      //读取状态
      const {isLikeMe}=this.state
          return <h2 onClick={this.handleClick}>{isLikeMe? '你喜欢我':'我喜欢你'}</h2>
    }
  }
  ReactDOM.render(<Like/>,document.getElementById('example'))
</script>
2.2 props
理解
  1. 每个组件对象都会有props(properties的简写)属性

  2. 组件标签的所有属性都保存在props中

  • class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。

  • 直接在标签上使用style属性时,要写成style={{}}是两个大括号,外层大括号是告知jsx这里是js语法,和真实DOM不同的是,属性值不能是字符串而必须为对象,需要注意的是属性名同样需要驼峰命名法。即margin-top要写成marginTop。

  • this.props.children 不要children作为把对象的属性名。因为this.props.children获取的该标签下的所有子标签。this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。官方建议使用React.Children.map来遍历子节点,而不用担心数据类型

作用
  1. 通过标签属性从组件外向组件内传递变化的数据

  2. 注意: 组件内部不要修改props数据

编码操作
  1. 内部读取某个属性值
this.props.propertyName
  1. 对props中的属性值进行类型限制必要性限制(已过时)
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}

新版本需要引入包prop-types.js

  1. 扩展属性: 将对象的所有属性通过props传递
… 的作用

1.打包

function fn(…as){} fn(1,2,3)

as就是数组类型

2.解包

const arr1 = [1,2,3]

const arr2 =[6,…arr1,9] 相当于替换为[6,1,2,3,9]

<Person {...person}/
  1. 默认属性值
Person.defaultProps = {
name: 'Mary'
}
  1. 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}

例子

//1.工厂方法
<script type="text/babel">

    /*
  需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
    1). 如果性别没有指定, 默认为男
    2). 如果年龄没有指定, 默认为18
    */

    //1.定义组件
    function Person(props) {
        return (
            <ul>
                <li>姓名:{props.name}</li>
                <li>年龄:{props.age}</li>
                <li>性别:{props.sex}</li>
            </ul>
        )
    }

    //指定属性默认值
    Person.defaultProps = {
      sex:'男',
      age:18
    }

    //指定属性的类型和必要性
    Person.propTypes = {
      name:PropTypes.string.isRequired,
      sex: PropTypes.string,
      age: PropTypes.number
    }

    //2.渲染组件标签
    const p1={
      name:"Tom",
      age:18,
      sex:'女'
    }
    const p2 = {
      name:"Mary"
    }

//  ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex}/>, document.getElementById('example1'));
    ReactDOM.render(<Person {...p1}/>, document.getElementById('example1'));

    ReactDOM.render(<Person name={p2.name}/>, document.getElementById('example2'))
</script>
//2.ES6组件
<script type="text/babel">

  /*
需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
  1). 如果性别没有指定, 默认为男
  2). 如果年龄没有指定, 默认为18
  */

  //1. 定义组件类
  class Person extends React.Component {
    render() {
      console.log(this)
      return (
        <ul>
          <li>姓名: {this.props.name}</li>
          <li>性别: {this.props.sex}</li>
          <li>年龄: {this.props.age}</li>
        </ul>
      )
    }
  }
  // 对标签属性进行限制
  Person.propTypes = {
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number
  }
  // 指定属性的默认值
  Person.defaultProps = {
    sex: '男',
    age: 18
  }

  //2. 渲染组件标签
  const person = {
    name: 'Tom',
    sex: '女',
    age: 18
  }
  ReactDOM.render(<Person {...person}/>, document.getElementById('example1'))
  const person2 = {
    myName: 'JACK',
    age: 17
  }
  ReactDOM.render(<Person name={person2.myName} age={person2.age}/>,
    document.getElementById('example2'))
</script>
2.3 refs与事件处理
理解
  1. 组件内的标签都可以定义ref属性来标识自己

a. <input type=“text” ref={input => this.msgInput = input}/>,this.msginput就相当于是这个input标签了

b. 回调函数在组件初始化渲染完或卸载时自动调用

  1. 在组件中可以通过this.msgInput来得到对应的真实DOM元素

  2. 作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据

事件处理
  1. 通过onXxx属性指定组件的事件处理函数(注意大小写)

a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件

b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)

  1. 通过event.target得到发生事件的DOM元素对象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target //返回input对象
}
编码操作
  <script type="text/babel">
    /*
    需求: 自定义组件, 功能说明如下:
      1. 界面如果页面所示
      2. 点击按钮, 提示第一个输入框中的值
      3. 当第2个输入框失去焦点时, 提示这个输入框中的值
   */
    //定义组件
    class MyComponent extends React.Component {
      constructor(props) {
        super(props) // 调用父类(Component)的构造函数
        //console.log(this)
        // 将自定义的函数强制绑定为组件对象
        this.handleClick = this.handleClick.bind(this) // 将返回函数中的this强制绑定为指定的对象, 并没有改变原来的函数中的this
        this.handleblur = this.handleblur.bind(this)
      }
      // 自定义的方法中的this默认为null
      handleClick () {
        // alert(this) //this默认是null, 而不是组件对象
        // 得到绑定在当前组件对象上的input的值
        alert(this.msgInput.value)
      }
      handleBlur (event) {
        alert(event.target.value)
      }
      render () {
        return (
          <div>
            <input type="text" ref={input => this.msgInput = input}/>{' '}
            <button onClick={this.handleClick}>提示输入数据</button>{' '}
            <input type="text" placeholder="失去焦点提示数据" onBlur={this.handleBlur}/>
          </div>
        )
      }
    }
    // 渲染组件标签
    ReactDOM.render(<MyComponent />, document.getElementById('example'))
  </script>
注意
  1. 组件内置的方法中的this为组件对象

  2. 在组件类中自定义的方法中this为null

a. 强制绑定this: 通过函数对象的bind()

b. 箭头函数(ES6模块化编码时才能使用)

3. 组件组合
功能界面的组件化编码流程(无比重要)
  1. 拆分组件: 拆分界面,抽取组件

  2. 实现静态组件: 使用组件实现静态页面效果

  3. 实现动态组件

a. 动态显示初始化数据

b. 交互功能(从绑定事件监听开始)

编码操作
<script type="text/babel">
    /*
    * 问题:数据保存在哪个组件内?
    *     看数据是某个组件需要(给它)还是某些组件需要(给共同的父亲)
    * 问题2:需要在子组件中改变父组件的状态?
    *     子组件中不能直接改变父组件的状态
    *     状态在哪个组件,更新状态的行为(方法)就应该定义在哪个组件
    *     解决:父组件定义函数,传递给子组件,子组件调用
    * */

    class App extends React.Component{
      constructor(props) {
        super(props);
        this.state = {
          //初始化状态
          todos: ['吃饭', '睡觉', 'code'],
          //test:['1','2','3']
        }
        this.addTodo = this.addTodo.bind(this)
        }

      addTodo(todo){
        const {todos} = this.state //相当于 const todos = this.state.todos {}是解构语法方便取值
        todos.unshift(todo)
        //更新状态
        this.setState({todos})
        //不能这么写
        // this.state.todos.unshift(todo)
        //更新状态
        //this.setState(this.state) 不会报错,但是这个相当于把原来的state在传给setState()有副作用
        //正确的应该是建立新state传进去
        //this.setState({this.state.todos})这种是新state但是就只有todos一个属性了,原state里其他属性就没了
        //所以要用解构语法(如下),顺序没要求
        //this.setState({todos,...this.state})

      }
      render(){
        return(
          <div>
            <h1>Simple To Do List</h1>
            <Add count={this.state.todos.length} addTodo = {this.addTodo}/>
            <List todos={this.state.todos}/>
          </div>
        )
      }
    }

    class Add extends React.Component{

      constructor(props) {
        super(props);

        this.add = this.add.bind(this)
      }

      add(addTodo){
//      1.读取输入的数据
        const todo = this.todoInput.value.trim()
//      2.检查合法性
        if(!todo) {
          return
        }
//      3.添加
        this.props.addTodo(todo)
//      4.清除输入
        this.todoInput.value = ''
      }

      render(){
        return(
          <div>
            <input type="text" ref={ myInput => this.todoInput = myInput}/>
            <button onClick={this.add}>add #{this.props.count+1}</button>
          </div>
        )
      }
    }

    class List extends React.Component{
      render(){
        return(
          <ul>
            {
              this.props.todos.map((value,index)=><li key={index}>{value}</li>)
          //或者this.props.todos.map((value,index)=>{return <li key={index}>{value}</li>})
          //为什么加了{}就要用return,因为{}默认是一个函数体
            }
          </ul>
        )
      }
    }

    Add.propTypes = {
        count:PropTypes.number.isRequired,
      addTodo:PropTypes.func.isRequired
    }

    List.propTypes = {
       todos:PropTypes.array.isRequired
    }

    ReactDOM.render(<App/>, document.getElementById('example'))
  </script>
4. 组件收集表单数据
理解
  • 问题: 在react应用中, 如何收集表单输入数据

  • 包含表单的组件分类

    • 受控组件: 表单项输入数据能自动收集成状态 如下面的name 简单一些
    • 非受控组件: 需要时才手动读取表单输入框中的数据 如下面的pwd 自动收集,建议用这个
编码操作
需求: 自定义包含表单的组件
  1. 输入用户名密码后, 点击登陆提示输入信息
  3. 不提交表单
<script type="text/babel">
  /*
  需求: 自定义包含表单的组件
    1. 界面如下所示
    2. 输入用户名密码后, 点击登陆提示输入信息
    3. 不提交表单
  */
  class LoginFrom extends React.Component{

    constructor(props) {
      super(props);

      //初始化状态
      this.state = {
        pwd:''
      }

      this.handleSubmit = this.handleSubmit.bind(this)
      this.handleChange = this.handleChange.bind(this)
    }

    handleSubmit(event){
      const name = this.nameInput.value
      //或者 const{value} = this,nameInput
      const {pwd} = this.state
      alert(`准备提交的用户名为:${name},密码为:${pwd}`)

      //阻止事件的默认行为(提交)
      event.preventDefault()
    }

    handleChange(event){
      //读取输入的值,
      const pwd = event.target.value
      //更新pwd状态
      //或者this.setState({pwd:event.target.value})
      this.setState({pwd})
    }
    //方法1:用ref 受控组件
    //方法2:用value和state以及onChange,原生js中onChange是失去焦点调用, 非受控组件
    //       这里我们用的是自定义dom事件,是value一改变就会调用
    render(){
      return(
        <form action="/test" onSubmit={this.handleSubmit}>

          用户名:  <input type="text" ref={input =>this.nameInput = input }/>

          密码:    <input type="password" value={this.state.pwd} onChange={this.handleChange}/>
          <input type="submit" value="登录"/>
        </form>
      )
    }
  }
ReactDOM.render(<LoginFrom/>, document.getElementById('example'))
</script>
5.组件生命周期

理解
  1. 组件对象从创建到死亡它会经历特定的生命周期阶段

  2. React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调

  3. 我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作

生命周期流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4n8vkl6U-1588255706689)(生命周期.png)]

生命周期详述
1) 组件的三个生命周期状态:

Mount:插入真实 DOM

Update:被重新渲染

Unmount:被移出真实 DOM

2)React 为每个状态都提供了勾子(hook)函数

componentWillMount()

componentDidMount()

componentWillUpdate()

componentDidUpdate()

componentWillUnmount()

3)生命周期流程

a.第一次初始化渲染显示: ReactDOM.render() 1次

constructor(): 创建对象初始化state

componentWillMount() : 将要插入回调

render() : 用于插入虚拟DOM回调

componentDidMount() : 已经插入回调

b.每次更新state: this.setSate() n次

componentWillUpdate() : 将要更新回调

render() : 更新(重新渲染)

componentDidUpdate() : 已经更新回调

c.移除组件: ReactDOM.unmountComponentAtNode(containerDom) 1次

componentWillUnmount() : 组件将要被移除回调

重要的勾子
  1. render(): 初始化渲染或更新渲染调用

  2. componentDidMount(): 开启监听, 发送ajax请求

  3. componentWillUnmount(): 做一些收尾工作, 如: 清理定时器

  4. componentWillReceiveProps(): 后面需要时讲

编码操作
需求: 自定义组件
  1. 让指定的文本做显示/隐藏的渐变动画
  2. 切换持续时间为2S
  3. 点击按钮从界面中移除组件界面
<script type="text/babel">
  /*
  需求: 自定义组件
    1. 让指定的文本做显示/隐藏的动画
    2. 切换时间为2S
    3. 点击按钮从界面中移除组件界面
   */
  class Fade extends React.Component {

    constructor (props) {
      super(props)
      console.log('constructor(): 创建组件对象')
      this.state = {
        opacity: 1
      }
      this.removeComponent = this.removeComponent.bind(this)
    }

    componentWillMount () {
      console.log('componentWillMount(): 初始化将要挂载')
    }

    componentDidMount () {// 在此方法中启动定时器/绑定监听/发送ajax请求
      console.log('componentDidMount(): 初始化已经挂载')
      // 保存到当前组件对象中
      this.intervalId = setInterval(function () {
        console.log('--------')
        // 得到当前opacity
        let {opacity} = this.state
        // 更新opacity
        opacity -= 0.1
        if(opacity<=0) {
          opacity = 1
        }
        // 更新状态
        this.setState({opacity})
      }.bind(this), 200)
    }

    componentWillUpdate () {
      console.log('componentWillUpdate(): 将要更新')
    }
    componentDidUpdate () {
      console.log('componentDidUpdate(): 已经更新')
    }

    componentWillUnmount () {// 清除定时器/解除监听
      console.log('componentWillUnmount(): 将要被移除')
      clearInterval(this.intervalId)
    }

    removeComponent () {
      ReactDOM.unmountComponentAtNode(document.getElementById('example'))
    }

    render() {
      console.log('render() 渲染组件')
      return (
        <div>
          <h2 style={{opacity:this.state.opacity}}>{this.props.content}</h2>
          <button onClick={this.removeComponent}>不活了</button>
        </div>
      )
    }
  }
  ReactDOM.render(<Fade content="react学不会, 怎么办?"/>, document.getElementById('example'))
</script>
6.虚拟DOM与DOM Diff算法

检测哪些需要更新哪些不需要更新,提高效率

基本原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vuhkQNYt-1588255706695)(虚拟DOM与Diff算法.png)]

编码操作
<script type="text/babel">
  /*
  验证:
  虚拟DOM+DOM Diff算法: 最小化页面重绘
  */

  class HelloWorld extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
          date: new Date()
      }
    }

    componentDidMount () {
      setInterval(() => {
        this.setState({
            date: new Date()
        })
      }, 1000)
    }

    render () {
      console.log('render()')
      return (
        <p>
          Hello, <input type="text" placeholder="Your name here"/>!&nbsp;
          <span>It is {this.state.date.toTimeString()}</span>
        </p>
      )
    }
  }

  ReactDOM.render(
    <HelloWorld/>,
    document.getElementById('example')
  )
</script>

React应用

1. React脚手架
理解
  1. xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
  • 包含了所有需要的配置
  • 指定好了所有的依赖
  • 可以直接安装/编译/运行一个简单效果
  1. react提供了一个用于创建react项目的脚手架库: create-react-app

  2. 项目的整体技术架构为: react + webpack + es6 + eslint

  3. 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化

创建并进入

npm install -g create-react-app

create-react-app hello-react

cd hello-react

npm start

npm root -g 查看全局下载的根目录

PS:在文件夹地址栏直接cmd可以直接打开此目录的cmd

react脚手架项目结构
  • 在文件package.json中

    • "dependencies"是开发(编译打包)依赖的环境配置
    • “devDependencies"是运行时依赖的环境配置
  • ReactNews

    |–node_modules—第三方依赖模块文件夹

    |–public

    ​ |–index.html-----------------主页面

    |–scripts

    |– build.js-------------------build**打包引用配置

    |– start.js-------------------start**运行引用配置

    |–src------------源码文件夹

    |–components-----------------react**组件

    ​ |–index.js-------------------应用入口js

    |–.gitignore------git版本管制忽略的配置

    |–package.json----应用包配置文件:

    ​ 1.标识:1)name version

    ​ 2.依赖:运行依赖和开发依赖

    ​ 3.运行/打包: scripts 通过npm run运行

    |–README.md-------应用描述说明的readme文件

  • 组件后缀名可以是.js/.jsx,一般是.jsx

  • 组件文件名小写,组件名首字母大写

  • 所有的组件类都要引入:

2. demo1 实现一个评论管理功能

点我

练习源代码

视频源代码

注意,原src文件可能已经改为src-对应的demo名,需要运行时要改回来

React ajax

1. 理解
1.1 前置说明
  1. React本身只关注于界面, 并不包含发送ajax请求的代码

  2. 前端应用需要通过ajax请求与后台进行交互(json数据)

  3. react应用中需要集成第三方ajax库(或自己封装)

1.2 常用的ajax请求库
  1. jQuery: 比较重, 如果需要另外引入不建议使用

  2. axios: 轻量级, 建议使用

​ a. 封装XmlHttpRequest对象的ajax

​ b. promise风格

​ c. 可以用在浏览器端和node服务器端

  1. fetch: 原生函数, 但老版本浏览器不支持

​ a. 不再使用XmlHttpRequest对象提交ajax请求

​ b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js

1.3 要求实现效果

要先引入axios库

需求:

  1. 界面效果如下
  2. 根据指定的关键字在github上搜索匹配的最受关注的库
  3. 显示库名, 点击链接查看库
  4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
2. axios
2.1 文档

https://github.com/axios/axios

2.2 相关API
2.2.1 get请求
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

2.2.2 post请求
axios.post('/user', {
 firstName: 'Fred',
    lastName: 'Flintstone'
})
.then(function (response) {
  console.log(response);
})
.catch(function (error) {
  console.log(error);
});

2.3 axios实现
需求:
  1. 界面效果如下
  2. 根据指定的关键字在github上搜索匹配的最受关注的库
  3. 显示库名, 点击链接查看库
  4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script type="text/babel">
  /*
  需求:
    1. 界面效果如下
    2. 根据指定的关键字在github上搜索匹配的最受关注的库
    3. 显示库名, 点击链接查看库
    4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
  */

  class MostStarRepo extends React.Component {

    state = {
      repoName: '',
      repoUrl: ""
    }

    componentDidMount() {
      const url = `https://api.github.com/search/repositories?q=r&sort=stars`

      //使用axios发送异步请求
            axios.get(url)
                .then(response=>{
                 const result = response.data
                  //console.log(result)
                  //console.log(response)
                  //得到数据
                  const{name,html_url} = result.items[0]
                  //更新状态
                  this.setState({repoName:name,repoUrl:html_url})
                  .catch((error)=>{
                    alert(error.message)
                  })
                })
    }

    render() {
      const {repoName, repoUrl} = this.state
      if (!repoName){
        return <h2>Loading......</h2>
      }else{
        return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>
      }
    }
  }

  ReactDOM.render(<MostStarRepo searchWord="r"/>, document.getElementById('example'))
</script>
3. Fetch
3.1 文档
  1. https://github.github.io/fetch/

  2. https://segmentfault.com/a/1190000003810652

3.2 相关API
3.2.1 get请求
fetch(url).then(function(response) {
  return response.json()
}).then(function(data) {
  console.log(data)
}).catch(function(e) {
  console.log(e)
});

3.2.2 post请求
fetch(url, {
  method: "POST",
  body: JSON.stringify(data),
}).then(function(data) {
  console.log(data)
}).catch(function(e) {
  console.log(e)
})
3.3 Fetch实现
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>11_ajax</title>
</head>
<body>
<div id="example"></div>

<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script type="text/babel">
  /*
  需求:
    1. 界面效果如下
    2. 根据指定的关键字在github上搜索匹配的最受关注的库
    3. 显示库名, 点击链接查看库
    4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
  */

  class MostStarRepo extends React.Component {

    state = {
      repoName: '',
      repoUrl: ""
    }

    componentDidMount() {
      const url = `https://api.github.com/search/repositories?q=r&sort=stars`
      //使用Fetch发送异步请求
     fetch(url)
        .then(response => {
          return response.json()
        })
        .then(data => {
          //得到数据
          const {name, html_url} = data.items[0]
          //更新状态
          this.setState({repoName: name, repoUrl: html_url})
        })
    }

    render() {
      const {repoName, repoUrl} = this.state
      if (!repoName) {
        return <h2>Loading......</h2>
      } else {
        return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>
      }
    }
  }

  ReactDOM.render(<MostStarRepo searchWord="r"/>, document.getElementById('example'))
</script>
</body>
</html>
4.demo2 实现github用户搜索功能

点我

自己实现的

别人实现的

记得下载包axios npm install --save axios

重要技术总结

1. 组件间通信
1.1 方式一: 通过props传递
  1. 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)

  2. 通过props可以传递一般数据和函数数据, 只能一层一层传递

  3. 一般数据–>父组件传递数据给子组件–>子组件读取数据

  4. 函数数据–>子组件传递数据给父组件–>子组件调用函数

1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
  1. 工具库: PubSubJS

  2. 下载: npm install pubsub-js --save

  3. 使用:

​ import PubSub from ‘pubsub-js’ //引入

​ PubSub.subscribe(‘delete’, function(data){ }); //订阅

​ PubSub.publish(‘delete’, data) //发布消息

实例 根据demo2改编

兄弟组件 爷孙组件之间通信 用这种方式比较好,不用再通过父组件传递

app.jsx 里面没有state等内容,因为孩子传递数据跟他没关系了

import React from 'react'
import Search from './search'
import Main from './main'

export default class App extends React.Component {

  render() {
    return (
      <div id="app">
      <div className="container">
        <Search />
        <Main />
      </div>
      </div>
    )
  }

}

search.jsx

1.3 方式三: redux
2. 事件监听理解
2.1原生DOM事件
  1. 绑定事件监听

​ a. 事件名(类型): 只有有限的几个, 不能随便写

​ b. 回调函数

  1.    触发事件
    

​ a. 用户操作界面

​ b. 事件名(类型)

​ c. 数据()

2.2 自定义事件(消息机制)
  1. 绑定事件监听

​ a. 事件名(类型): 任意

​ b. 回调函数: 通过形参接收数据, 在函数体处理事件

  1. 触发事件(编码)

​ a. 事件名(类型): 与绑定的事件监听的事件名一致

​ b. 数据: 会自动传递给回调函数

3. ES6常用新语法
  1. 定义常量/变量: const/let

  2. 解构赋值: let {a, b} = this.props import {aa} from ‘xxx’

  3. 对象的简洁表达: {a, b}

  4. 箭头函数:

​ a.常用场景

​ 组件的自定义方法: xxx = () => {}

​ 参数匿名函数

​ b.优点:

​ 简洁

​ 没有自己的this,使用引用this查找的是外部this

  1. 扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)

  2. 类: class/extends/constructor/super

  3. 工具库: PubSubJS

  4. 下载: npm install pubsub-js --save

  5. 使用:

​ import PubSub from ‘pubsub-js’ //引入

​ PubSub.subscribe(‘delete’, function(data){ }); //订阅

​ PubSub.publish(‘delete’, data) //发布消息

实例 根据demo2改编

兄弟组件 爷孙组件之间通信 用这种方式比较好,不用再通过父组件传递

app.jsx 里面没有state等内容,因为孩子传递数据跟他没关系了

import React from 'react'
import Search from './search'
import Main from './main'

export default class App extends React.Component {

  render() {
    return (
      <div id="app">
      <div className="container">
        <Search />
        <Main />
      </div>
      </div>
    )
  }

}

search.jsx

1.3 方式三: redux
2. 事件监听理解
2.1原生DOM事件
  1. 绑定事件监听

​ a. 事件名(类型): 只有有限的几个, 不能随便写

​ b. 回调函数

  1.    触发事件
    

​ a. 用户操作界面

​ b. 事件名(类型)

​ c. 数据()

2.2 自定义事件(消息机制)
  1. 绑定事件监听

​ a. 事件名(类型): 任意

​ b. 回调函数: 通过形参接收数据, 在函数体处理事件

  1. 触发事件(编码)

​ a. 事件名(类型): 与绑定的事件监听的事件名一致

​ b. 数据: 会自动传递给回调函数

3. ES6常用新语法
  1. 定义常量/变量: const/let

  2. 解构赋值: let {a, b} = this.props import {aa} from ‘xxx’

  3. 对象的简洁表达: {a, b}

  4. 箭头函数:

​ a.常用场景

​ 组件的自定义方法: xxx = () => {}

​ 参数匿名函数

​ b.优点:

​ 简洁

​ 没有自己的this,使用引用this查找的是外部this

  1. 扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)

  2. 类: class/extends/constructor/super

  3. ES6模块化: export default | import

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React 18是React的最新版本,它引入了一些新的功能和改进。在学习React 18时,你可以关注以下几个方面: 1. React组件:React组件是构建用户界面的基本单元。你可以使用React.createElement()函数或JSX语法来创建React元素和组件。React元素是不可变的,而React组件是可复用的。\[1\] 2. react-dom.development.js或react-dom/client模块:这些模块提供了处理真实DOM的功能,包括Diff算法和渲染成真实DOM的过程。你可以在HTML文件中引入这些模块,并使用ReactDOM.createRoot()方法来渲染React的DOM。\[2\] 3. Hook:Hook是React中的特殊函数,它允许你在函数组件中添加状态和其他特性。例如,useState是一个Hook,它可以让你在函数组件中添加状态。你可以使用useState来定义和更新状态,并在组件中使用它们。\[3\] 在学习React 18时,你可以通过阅读官方文档、参考教程和实践项目来深入了解这些概念和用法。同时,你也可以与其他开发者交流和分享经验,加深对React的理解。 #### 引用[.reference_title] - *1* *2* *3* [2023年React18笔记【慕课网imooc】【尚硅谷】【Vue3+React18 + TS4考勤系统】](https://blog.csdn.net/qq_28838891/article/details/124598439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值