React

React

1.React核心概念

1.React 使用

单页面调试代码

 <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone"></script>

注意: 使用React语法需要将vscode中的js编译模式变成js-React模式

 <script type="text/babel">
      {/* 1. 使用实例   将h1内容插入id名为example的节点中 */}
      ReactDOM.render(
        <h1>React Example</h1>,
        document.getElementById('React')
      )
2.npm使用React语法
  • 安装React语法并创建项目
$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
  • 项目目录

    my-app/
      README.md
      node_modules/
      package.json
      .gitignore
      public/
        favicon.ico
        index.html
        manifest.json  #指定了开始页面为index.html  是代码的源头
      src/
        App.css
        App.js
        App.test.js
        index.css
        index.js
        logo.svg
    
3.React元素渲染

元素是构成React应用的最小单位,用于描述屏幕上输出的内容

Ract中的元素事实上是普通的对象 ReactDOM可以确保浏览器DOM的数据内容与React中的元素相同

const Element = hello woorld!  
4.更新元素渲染

React中的元素都是不可变的 当元素被创建之后 是无法改变内容和属性的

比如创建一个定时器 获取当地时间  结果获取到的时间都是相同的
6.JSX简介
  • 语法简介
// jsx语法简介
// jsx语法中可以使用表达式 用{} 代替变量
const autor = '王万琦'
const element = <h1>这个人的姓名是{autor}</h1>
  • jsx防止注入攻击

  • jsx表示对象

两种语法相同

jsx语法一:
const element = (<h1 className='green'>wangwanqi </h1>)
jsx语法二:
const element = React.createElement('h1',{ className:'green'},wangwanqi)                 
 简化过后的结构:
// 注意:这是简化过的结构
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};
7.函数组件与class组件
  • 定义函数组件

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }class组件
    
  • class组件 es6语法

class Welcome extends React.component{
  render(){
     return <h1>Hello, {props.name}</h1>;
  }
}
  • 渲染组件

React元素可以是用户自定义的组件

const element = <Welcome name='王万琦'>
#当React元素为用户自定义组件是  他会将jsx所接收的属性attributes以及子组件(clildren)转换成单个对象传递给组件
#这个对象称为props

例如:

function Welcome (props) {
  return <h1 > {props.name}</h1>
}
const element =<Welcome name='王万琦'>
ReactDOM.render(
  element,
  document.getElementById('root')
);
#过程
1.调用render函数, 并传入<Welcome name='王万琦'>
2.React调用Welcome组件, 并将{name:'王万琦'}作为props传入
3.Welcome组件将<h1 >王万琦</h1> 元素作为返回值
4.ReactDom将Dom高效的更新为<h1 >王万琦</h1>
  • 组件名称必须以大写字母开头,如果是小写字母 React会将其认为原生dom标签

  • 组合组件


#组件可以在其输出时引用其他组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

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

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
  • 组件的封装
const GetAuthor = function (props) {
  return (
    <div className="author">
      <div>姓名: {props.author}</div>
      <div>住址: {props.adress}</div>
      <div>联系方式: {props.tel}</div>
    </div>
  )
}
export default GetAuthor

8.state与生命周期

state与props类似 但是state是私有的 , 并且完全受控于当前组件

  • props的只读性

组件无论是使用函数声明 还是 class声明 , 都绝不能修改自身的props

所有React组件都必须像纯函数那样保护他们的props不被更改,即传入的props

不能发生任何变动

  • 将函数组件转换成class组件
  1. 创建一个同名的es6class 并且继承React.component
  2. 创建一个空的render体 ,
  3. 将函数体转移到render中
  4. 在render函数中将props中引用的props.author 等属性改为this.props.author
  5. 删除剩余的函数声明
class Getauthor  extends React.Component(
render() {
  return  (
    <div className="author">
      <div>姓名: {this.props.author}</div>
      <div>住址: {this.props.adress}</div>
      <div>联系方式: {this.props.tel}</div>
    </div>
  )
  }
) 
  • 向class组件中添加局部的state

通过以下三部将date从props移动到state中

  • 把render()方法中的this.props的date替换成this.state.date
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div>
    );
  }
}
  • 添加一个class构造函数, 然后将函数中的this.state
class Clock extends React.Component {
  //只有使用super 才能使用this关键字 否则会报错 这是应为子类实例的构建基于父类实例 只有super方法才能调用父类实例
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

通过以下方式将props传递到父类的构造函数中

constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  • 3.移除组件Clock元素中的date属性
ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
  • 4.设置计时器并且每秒更新他

  • 将声明周期方法添加到class中

当组件第一次被渲染到dom的时候就设置一个计时器 在react中称为挂载mount

当dom中组件被删除的时候应该清除计时器 称为卸载 unmount

我们可以为class组件声明一些特殊的方法 当组件挂载或卸载时去执行这些方法 这些方法称为声明周期方法

componentDidMount 挂载
componentWillUnmount 卸载

完整代码实例

// const GetAuthor = function (props) {
//   return (
//     <div className="author">
//       <div>姓名: {props.author}</div>
//       <div>住址: {props.adress}</div>
//       <div>联系方式: {props.tel}</div>
//       <div>当地时间: {new Date().toLocaleTimeString()}</div>
//     </div>
//   )
// }
// 使用state
import React from 'react'

// 创建class类 继承于React.component
// 添加render方法
// super定义this 并且传入props
// 组件中删除传入的方法
// 这样state就变成了响应式的 不需要书写 循环异步定时器
console.log(React)
class GetAuthor extends React.Component {
  constructor(props) {
    super(props)
    // 定义state初始参数
    this.state = {
      date: new Date(),
    }
  }
  render() {
    return (
      <div className="author">
        <div>姓名: {this.props.author}</div>
        <div>住址: {this.props.adress}</div>
        <div>联系方式: {this.props.tel}</div>
        <div>当地时间: {this.state.date.toLocaleTimeString()}</div>
      </div>
    )
  }
  trick() {
    // 不能直接直接修改state中的内容 这是React的保护机制
    // this.state.date = new Date()
    // 正确写法:
    let tempState = JSON.parse(JSON.stringify(this.state))
    tempState.date = new Date()
    this.setState(tempState)
  }
  // `挂载执行
  componentDidMount() {
    // 不能这样写 定时器中的函数需要为箭头函数 来获取this指向
    // this.timeID = setInterval(this.trick(), 1000)
    this.timeID = setInterval(() => {
      this.trick()
    }, 1000)
  }
  // 卸载执行函数
  componentWillUnmount() {
    window.clearInterval(this.timeID)
  }
}
export default GetAuthor

响应刷新原理:王万琦

浏览器每秒都会调用一次 tick() 方法。 在这方法之中,Clock 组件会通过调用 setState() 来计划进行一次 UI 更新。得益于 setState() 的调用,React 能够知道 state 已经改变了,然后会重新调用 render() 方法来确定页面上该显示什么。这一次,render() 方法中的 this.state.date 就不一样了,如此以来就会渲染输出更新过的时间。React 也会相应的更新 DOM。

9.正确使用state

不要直接修改state 如要修改 使用setState重新定义

构造函数是唯一可以给this.state赋值的地方

State的更新可能是异步的 处于性能考虑 React可能把多个setState()调用合并成一个调用

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
constructor(props) {
    super(props);
    this.state = {
      posts: [],      comments: []    };
  }

可以分别调用 不用重新设置

 componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments      });
    });
  }
10.事件处理

React事件的命名采用小驼峰命名 而不是全小写

使用jsx语法是需要传入一个函数 作为事件处理函数,而不是字符串

传统html
<button onclick="activateLasers()">
  Activate Lasers
</button>

React事件处理

<button onClick={activateLasers}>  Activate Lasers
</button>

使用的方法必须更改this指向 方法如下,如果不更改this指向 调用方法会报undefined

 constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // 为了在回调中使用 `this`,这个绑定是必不可少的    this.handleClick = this.handleClick.bind(this);  
 }

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

参数传递的两种方式 更改this指向方式

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

函数组件渲染是书写的两种方式

<ul>
            {/* <ListItems></ListItems> */}
            {ListItems()}
          </ul>
11.表单
  • input
  • texxarea
  • select

以上三种都是通过change进行将更改的数据设置成state中的数据

从而是state变成唯一数据源

注意: React的更新时异步的所有更新state之后获取state有可能不是最新的数据,如果是表单checkbox 可能获取到相反的结果

#原因:  React中的state更新是异步的,不能依赖state中的计算结果去进行下一步的state
import React from 'react'
class CheckGroup extends React.Component {
  constructor(props) {
    super(props) //访问props
    // 设置默认赋值
    this.state = {
      author: 'wangwanqi',
      isCheck: true,
    }
    this.handleChange = this.handleChange.bind(this)
  }
  render() {
    return (
      <div>
        <label>
          姓名:
          <input
            type="text"
            name="author"
            value={this.state.author}
            onChange={this.handleChange}
          />
        </label>
        <label>
          统计登录次数:
          <input
            type="checkbox"
            onChange={this.handleChange}
            name="isCheck"
            checked={this.state.isCheck}
          />
        </label>
      </div>
    )
  }
  handleChange(event) {
    const target = event.target
    const type = target.type
    const name = target.name
    const value = type === 'checkbox' ? target.checked : target.value
    this.setState({
      [name]: value,
    })
      /**只能异步获取**/
    setTimeout(() => {
      console.log(this.state)
    }, 1000)
  }
}
export default CheckGroup

实现同步更新方式

第一种:

添加异步函数 定时器

第二种:

test(){

this.setState((props)=>({//props指定的是state对象

num:props.num+1 //实现state的num属性值加1

}));

}


12.状态提升

通常, 多个组件需要反应相同的变化数据 这是需要共享状态提升到最近的共同父组件中

个人理解: 多个子组件如果其中一个组件变化了 其他子组件同步发生变化

主要方式:

  • 将子组件的值设置为父组件传递进来的值
  • 检测子组件的变化
  • 子组件变化后 执行父组件传递进来的props中的方法
  • 父组件定义传给子组件的方法,接受子组件传递进来的值
  • 将子组件传递进来的值赋值给父组件中的state
  • 这样子组件都是用的父组件传递进来的值 完成妆台同步
<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone"></script>
</head>

<body>
    <div id="app"></div>

    <script type="text/babel">
        class Input extends React.Component {
            constructor(props) {
                super(props)
                this.handleChange = this.handleChange.bind(this)
            }

            handleChange(e) {
                this.props.onContentChange(e.target.value)
            }

            render() {
                return (
                    <input type='text' value={ this.props.content } onChange={ this.handleChange } />
                )
            }
        }
        //父组件
        class AllInput extends React.Component {
            constructor(props) {
                super(props)
                this.state = { content: '' }
                this.handleContentChange = this.handleContentChange.bind(this)
            }

            handleContentChange(newContent) {
                this.setState({ content: newContent })
            }

            render() {
                return (
                    <div>
                        <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                        <br /><br />
                        <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                    </div>
                )
            }
        }
        
        ReactDOM.render(
            <AllInput />,
            document.getElementById('app')
        )
    </script>
</body>

</html>
13.组合与继承

组件可以接受任意 props,包括基本数据类型,React 元素以及函数。

上一篇:Shiro中认证的关键对象


下一篇:Oracle学习之路-SQL篇-连接查询