zoukankan      html  css  js  c++  java
  • React

    笔记来自
    github实例
    immutable的学习
    面试题
    手写实现react

    需要学的知识有

    • 脚手架安装启动
    • JSX组件基础使用,修改数据,for,if,事件...
    • JSX组件传参通信
    • 生命周期
    • 路由
    • Redux
    • React-Hooks
    • 打包发布
    • 首屏优化,Next服务器渲染

    安装脚手架

    • 普通的命令
    # 一个电脑安装一次就好
    cnpm install -g create-react-app
    # 创建项目
    create-react-app 【name】
    
    cnpm install
    npm start
    
    • 脚手架有什么
    // 自带了Ject测试插件
    // eslint代码规范检查
    // PWA功能的 manifest.json 和 serviceWorker.js 文件
    
    // 入口文件 index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    // 这是一个组件
    import App from './App';
    // import * as serviceWorker from './serviceWorker';
    
    // 这个就是jsx写法
    // 后面等引入了路由和redux后得修改,具体往下看
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    // PWA没用注释了
    // serviceWorker.unregister();
    

    脚手架设置

    • 跨域请求
    // 安装
    npm i http-proxy-middleware --save
    
    // 在src下创建setupProxy.js,名字固定
    const { createProxyMiddleware } = require('http-proxy-middleware');
    module.exports = function(app) {
        app.use('/api', 
            createProxyMiddleware({ 
                target: 'http://xxx.pdt1997.top/', 
                changeOrigin: true 
            })
        );
    }
    
    // axios安装设置查看【axios和fetch】笔记
    
    • 打包文件的配置查看【React打包配置】笔记

    基础使用

    • 组件的结构
    // vue是一个template+script+style组成的
    // 而react是一个js文件加一个css文件,建议创建一个文件夹装起来使用,再一起装进pages文件夹里比较规范
    
    // app.js
    import React from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
            </p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
            </a>
          </header>
        </div>
      );
    }
    
    // 上面的写法不规范,应该改成下面的写法
    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    // 这里面的一级属性都不需要逗号结束
    class App extends Component{
        // 这个就是vue的data
        state = {
            msg: "测试",
        }
        render(){
            return (
                <div className="App">
                    <header className="App-header">
                        <div>{this.state.msg}</div>
                        <img src={logo} className="App-logo" alt="logo" />
                        <p>
                            Edit <code>src/App.js</code> and save to reload.
                        </p>
                        <a
                            className="App-link"
                            href="https://reactjs.org"
                            target="_blank"
                            rel="noopener noreferrer"
                        >
                            Learn React
                        </a>
                    </header>
                </div>
            );
        }
    }
    
    export default App;
    
    • 修改数据,在react应该叫修改状态state
    // 不要直接修改 state(状态)
    // this.state.comment = 'Hello';
    // 上述代码并不会重新渲染组件,需要使用this.setState()代替:
    // 正确操作
    this.setState({
      comment: 'Hello'
    });
    
    //  state(状态) 更新可能是异步的
    // React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。
    // 因为this.props和this.state 可能是异步更新的,你不能依赖他们的值计算下一个state(状态)
    // this.setState({
      // counter: this.state.counter + this.props.increment,
    // });
     
    
    // 我们并不能通过上述代码得到想要的值
    // 为了弥补这个问题,使用另一种 setState() 的形式,接受一个函数
    // 这个函数将接收前一个状态作为第一个参数,应用更新时的 props 作为第二个参数,代码如下:
    this.setState((prevState, props) => ({
      counter: prevState.counter + props.increment
    }));
    
    • 事件绑定
    class Toggle extends React.Component {
      state = {
        isToggleOn: true,
      }
      // 一定要箭头函数,否则没有this
      handleClick = (e) => {
        // 这就是修改state方法
        this.setState({
          isToggleOn: !this.state.isToggleOn
        });
      }
      // event永远在最后一位参数
      handleClick2 = (msg,e) => {
        console.log(msg)
      }
      render() {
        return (
          <button onClick={this.handleClick('test')}>
            {this.state.isToggleOn ? 'ON' : 'OFF'}
          </button>
          // 如果要传参就得加上bind(this,参数)
          <button onClick={this.handleClick2.bind(this,'test')}>
            {this.state.isToggleOn ? 'ON' : 'OFF'}
          </button>
        );
      }
    }
    
    • 条件渲染
    // 三元
    render() {
      return (
        <div>
          { this.state.isLoggedIn ? (
            <LogoutButton onClick={this.handleLogoutClick} />
          ) : (
            <LoginButton onClick={this.handleLoginClick} />
          ) }
        </div>
      );
    }
    
    // 是否 &&
    render() {
      return (
        <div>
          <h1>Hello!</h1>
          { unreadMessages.length > 0 &&
            <h2>
              您有 {unreadMessages.length} 条未读信息。
            </h2>
          }
        </div>
      );
    }
    
    • 列表渲染
    render() {
      return (
        <div>
          { 
            this.state.selectedProList.map((item, index) => {
              return <li key={index} className="selected-pro-item ellipsis">{item.product_name}x{item.selectNum}</li>
            })
          }
        </div>
      );
    }
    

    JSX组件传参通信

    • 所有的数据和方法都在this.props对象里
    • 父传子
    // 父
    render(){
       return(
             <Child {...person} />
             <Child txt={this.state.message}/>
       )
    }
    // 子
    render(){
       return(
             <div>{this.props.name}</div>
             <div>{this.props.age}</div>
             <div>{this.props.message}</div>
       )
    }
    
    • 子传父,子组件调用父组件的方法进行数据的传递
    // 父
    getDatas(msg){
        //把子组件传递过来的值赋给this.state中的属性
        this.setState({
          mess: msg
        });
    }
    render(){
        return (
             <Son getdata={this.getDatas.bind(this)}></Son>
             <div>展示数据:{this.state.mess}</div>
        );
    }
    
    // 子
    handleClick(){
        //通过props属性获取父组件的getdata方法,并将this.state值传递过去
        this.props.getdata(this.state.inputValue);
    }
    render(){
        return (
            <button onClick={this.handleClick.bind(this)}>点击获取数据</button>
        );
    }
    
    • 兄弟,组件A传值父组件,父组件传值组件B,就是把上面的
    // 父
    getDatas(msg){
        //把子组件传递过来的值赋给this.state中的属性
        this.setState({
          mess: msg
        });
    }
    render(){
        return (
             <SonA getdata={this.getDatas.bind(this)} />
             <SonB mess={mess} />
        );
    }
    
    • 组件传值可以使用prop-type这个插件进行格式判断和默认值使用
    • 跟vue一样,数据之间的传递非常的麻烦,应该是用第三方的数据储存插件redux

    生命周期

    • 核心 constructor 》componentWillMount 》render 》componentDidMount
    class Button extends Component {
      state = { 
         data: 0 
      }
      setNewNumber() {
        this.setState({data: this.state.data + 1})
      }
      render() {
          return (
             <div>
                <button onClick = {this.setNewNumber.bind(this)}>INCREMENT</button>
                <Content myNumber = {this.state.data}></Content>
             </div>
          );
        }
    }
     
     
    class Content extends Component {
      componentWillMount() {
          // 在渲染前调用,在客户端也在服务端
          console.log('Component WILL MOUNT!')
      }
      componentDidMount() {
          //  在第一次渲染后调用,只在客户端
          //  初始化请求写在这
          //  为什么不写在componentWillMount 
          //  因为componentWillMount方法的调用在constructor之后,在render之前,在这方法里的代码调用setState方法不会触发重渲染,所以它一般不会用来作加载数据之用,它也很少被使用到
          console.log('Component DID MOUNT!')
      }
      componentWillReceiveProps(newProps) { 
          console.log('Component WILL RECEIVE PROPS!')
      }
      shouldComponentUpdate(newProps, newState) {
          // 这个是数据更新前会执行的方法,如果返回false,页面不会更新
          // 这个的用处特别的大,如果你在render里打印一下666,会发现每次数据更新实际都调用了无数次的render,非常的损耗性能
          // 当然必须要的不能阻止,如果是前后一样的数据应该避免render的更新,所以在这里可以对两个参数进行一致性判断,一样则返回false
          // 可是这个数据的判断就是深拷贝,深拷贝的性能也是非常的离谱,也不好完成
          // 所以在这里应该使用插件,也就是最上的那个immutable插件
          // 引用这个插件后,整个项目的数据都应该改用插件里使用的【List和Map和Set和其他】,按照他要求的方法进行数据变化
          // 具体自行学习
          return true;
      }
      componentWillUpdate(nextProps, nextState) {
           console.log('Component WILL UPDATE!');
      }
      componentDidUpdate(prevProps, prevState) {
           // 数据更新调用
           console.log('Component DID UPDATE!')
      }
      componentWillUnmount() {
           // 销毁前
           console.log('Component WILL UNMOUNT!')
      }
     
      render() {
         return (
            <div>
              <h3>{this.props.myNumber}</h3>
            </div>
         );
      }
    }
    
  • 相关阅读:
    十万个为什么 —— 理化篇
    地行、地貌
    工业镜头基础知识整理
    parfor —— matlab 下的并行循环
    浅谈设计模式在GIS中的应用
    android ellipsize 属性详解
    Servlet 学习总结-1
    搜索引擎有用的外链建设的方式
    Servlet 学习总结-2
    如何用批处理命令批量配对重命名
  • 原文地址:https://www.cnblogs.com/pengdt/p/13070740.html
Copyright © 2011-2022 走看看