React入门指南

React简要总结

起步

  1. 创建项目: npx create-react-app my-app
  2. 打开项目: cd my-app
  3. 启动项目: npm start
  4. 暴露配置项: npm run eject
├── README.md ⽂文档
├── public 静态资源
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src 源码
├── App.css
├── App.js 根组件
├── App.test.js
├── index.css 全局样式
├── index.js ⼊入⼝口⽂文件
├── logo.svg
└── serviceWorker.js pwa⽀支持
├── package.json npm 依赖

JSX简介

  • jsx理解为js和xml的杂交品种,注意他不是字符串

    • JSX 中可以嵌入表达式
    const name = 'Josh Perez';
    const element = <h1>Hello, {name}</h1>;//嵌入表达式
    
    • JSX也可以作为表达式
    function getGreeting(user) {
      if (user) {
        return <h1>Hello, {formatName(user)}!</h1>; //作为表达式
      }
      return <h1>Hello, Stranger.</h1>;//作为表达式
    }
    
    在浏览器环境处理JSX

    借助Babel 会把 JSX 转译成一个名为 React.createElement()*(也就是vue里的常说的h函数 )*函数调用。

    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    

    ===

    const element = React.createElement(//也就是vue里的常说的h函数
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    
    JSX 使用注意事项
    • 必须有,且只有一个顶层的包含元素 - React.Fragment
    • JSX 不是html,很多属性在编写时不一样
      • className
      • style
    • 列表渲染时,必须有 key 值
    • 在 jsx 所有标签必须闭合
    • 组件的首字母一定大写,标签一定要小写
    元素渲染

    通过ReactDOM.render(Vnode, container[, callback])函数,可以将jsx转变为DOM元素

    • element:要渲染的内容
    • container:要渲染的内容存放容器
    • callback:渲染后的回调函数
    const element = <h1>Hello, world</h1>; //jsx表达式
    ReactDOM.render(element, document.getElementById('root'));//渲染成<h1>Hello, world</h1> DOM元素
    

组件

可复用的功能块,允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思

从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。

类组件

  • 必须继承 React.Component
  • 必须有 render 方法
import React, { Component } from 'react';
export default class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

函数组件

  • 函数的名称就是组件的名称
  • 函数的返回值就是组件要渲染的内容
import React from 'react'
export default function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

组件间通信

和vue类似,父传子通过props,子传父通过事件派发

<Child 
     name={name} 
     editName = {this.editName}  
/>

//子组件的jsx
<p>姓名: {name}</p>
<button onClick={()=>{
  editName("开课吧");
}}>修改姓名</button>

props和state

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

props

外部传递给组件的响应式参数

类组件props获取

在render函数中通过this.props获得

const item ={ title: `家人`, content: [{ name: `爸爸` }, { name: `爸爸` }]};
<Dllist  contentData ={item} />

class Dllist extends Component {
    render() {
        let { contentData } = this.props;
    }
}
函数组件中props获取
const data ='传递的数据';
<Newtodo name={data}/>
export default function Newtodo(props) {
    const {name} = props
}

state

组件内部的响应式参数,

state 状态,是 Component 的属性,我们会将组件相关的数据放入 state ,然后通过 state 属性 和 组件要构建的视图进行绑定,当 state 更新时,同步会更新我们的视图

state状态的修改
  • setState(updater, [callback])
    • updater: 更新数据 FUNCTION/OBJECT
    • callback: 更新成功后的回调 FUNCTION
    • 异步:react通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能
    • 浅合并 Objecr.assign()
    • 调用 setState 之后,会触发生命周期,重新渲染组件
  • setState为异步操作,这点和vue一样,都是为了性能考虑
  • setState为浅合并
类组件state的声明和使用
class App extends Component {
  state={
    data:{
      count: 1,
      name: "kkb"
    }  
  }
  render(){
    let {count,name} = this.state.data;
    return <div>
      <p>{name}</p>
      <strong>{count}   </strong>
      <button onClick={()=>{
        this.setState({
          data: {
            ...this.state.data,
            count: count + 1
          }
        });
      }}>递增</button>
    </div>  
  }
}
函数组件state的声明和使用(搭配hook使用)

组件生命周期

在这里插入图片描述

相比vue 生命周期的单纯,react 生命周期各种花里胡哨,真的可能会用也就是componentDidMount/componentDidUpdata/componentWillUnmount

ref

和vue的refs一样,获得DOM元素

下面是几个适合使用 refs 的情况:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

避免使用 refs 来做任何可以通过声明式实现来完成的事情。

类组件中使用ref

import React, { Component, createRef } from 'react'

export default class List extends Component {
  constructor(props) {
    super(props);
    // 创建一个 ref 来存储 textInput 的 DOM 元素
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // 直接使用原生 API 使 text 输入框获得焦点
    // 注意:我们通过 "current" 来访问 DOM 节点
    this.textInput.current.focus();
  }

  render() {
    // 告诉 React 我们想把 <input> ref 关联到
    // 构造器里创建的 `textInput` 上
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数

hook规则

1. 只在最顶层使用 Hook
2. 只在React函数中调用Hook
 - 在 React 的函数组件中调用 Hook
 -  在自定义 Hook 中调用其他 Hook 

state hook — useState

useState整合了类组件的state和setState方法,函数通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。

const [state, setState] = useState(initialState);

1.  [状态,修改该状态的方法] = useState(初始值);
2.  在同一个组件中可以使用 useState 定义多个状态
3.  注意 useState 返回的 setState 方法,不会进行对象合并
4.  注意 useState 返回的 setState 方法同样是异步方法
import React, { useState } from "react";
export default function App(props) {
  const [name,setName] = useState("kkb");
  const [count,setCount] = useState(1);
  return <div>
      <p>{name}</p>
      <p>{count}</p>
      <button onClick={()=>{
          setCount(count+1);
      }}>递增</button>
  </div>
}

Effect Hook — useEffect

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 使用浏览器的 API 更新页面标题
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
useEffect 执行顺序
useEffetc(()=>{
    console.log('这是回调函数')
    return ()=>{
        console.log('这是返还函数')
    }
},[data])
//组件挂载完成或data修改引起的组件更新完之后执行
useEffect(()=>{},[]);// 组件挂载完成
  • 挂载过程
    • 组件挂载成功 --> 回调函数
  • 更新过程
    • 组件即将更新 --> 执行 useEffect 的返还函数 --> 组件更新 --> useEffect 的回调函数
  • 卸载过程
    • 执行 useEffect 的返还函数

useRef

函数组件中使用ref

import React, { useEffect, useState, useRef } from "react";
function Child(props) {
  const {name,setName} = props;
  const [count,setCount] = useState(1);
  const countP = useRef(null);
  useEffect(()=>{
    console.log(countP.current);
  });
  return <div>
      <p>{name}</p>
      <button onClick={()=>{
        setName("开课吧");
      }}>中文名</button>
      <p ref={countP}>{count}</p>
      <button onClick={()=>{
          setCount(count+1);
      }}>递增</button>
  </div>
}

export default Child;

自定义hook

  • 自定义 Hook 必须以 “use” 开头
  • 两个组件中使用相同的 Hook 不会共享 state

由于自定义hook中可以调用其他hook,那么自定义hook可以将某个重复功能进行封装并实现数据响应式,必须返回[参数,函数]

import React, { useState, useEffect } from "react";
/*
  自定义 hook 
  要求命名必须以 use 开始
*/
function useScrollY() {
  const [scrollY,setScrollY] = useState(0);
  useEffect(()=>{
    window.onscroll = function () {
      setScrollY(window.scrollY);
    }
    setScrollY(window.scrollY);
    return ()=>{
      window.onscroll = null;
    }
  },[]);
  return [scrollY,(y)=>{
      window.scrollTo(0,y);
      setScrollY(y);
  }]
}
export {useScrollY}

Hook API 目录

router

提供声明性的、可访问的导航

React Router 提供了多种不同环境下的路由库

  • web: npm i -S react-router-dom

  • native

router原理概要

实现两个组件,Link/NavLink 组件将配置转变为a标签,Router同时监听浏览器的hashchange 或者 url变更,当变更时Route组件根据当前url信息匹配到对应路由并进行渲染

Link组件

  • to: string
    • Link 的地址字符串表示形式,通过连接位置的 pathname, search, and hash创建。
<Link to="/about">About</Link>
  • to: object

    • object可以是如下属性
      • pathname: A string representing the path to link to.
      • search: A string representation of query parameters.
      • hash: A hash to put in the URL, e.g. #a-hash.
      • state: State to persist to the location.
    <Link
      to={{
        pathname: "/courses",
        search: "?sort=name",
        hash: "#the-hash",
        state: { fromDashboard: true }
      }}
    />
    
  • to: function

    • 作为参数传递到的函数,它应该返回以符串或对象的形式
    <Link to={location => ({ ...location, pathname: "/courses" })} />
    <Link to={location => `${location.pathname}?sort=name`} />
    

NavLink组件

​ 的一个特殊版本,当呈现的元素与当前URL匹配时,它将向该元素添加样式属性。

  • activeClassName: string
    • 当元素处于活动状态时,类名对应的样式将会执行。默认的给定类是active。这将与类名prop连接起来
<NavLink to="/faq" activeClassName="selected">
  FAQs
</NavLink>
<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: "bold",
    color: "red"
  }}
>
  FAQs
</NavLink>
<NavLink
  to="/events/123"
  isActive={(match, location) => {
    if (!match) {
      return false;
    }

    // only consider an event active if its event id is an odd number
    const eventID = parseInt(match.params.eventID);
    return !isNaN(eventID) && eventID % 2 === 1;
  }}
>
  Event 123
</NavLink>

Route组件

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";

ReactDOM.render(
  <Router>
    <div>
      <Route exact path="/">
        <Home />
      </Route>
      <Route path="/news">
        <NewsFeed />
      </Route>
    </div>
  </Router>,
  node
);

…后面的内容待补充

redux

redux 上手指南

  • 创建store

    • 定义reducer初始化state并定义state修改规则
    • 通过dispatch一个action来提交对数据的修改
    • action提交到reducer函数⾥里里,根据传⼊入的action的type,返回新的state
    import { createStore } from "redux";
    const reducer = (state = {
        todos: [{ id: 1, title: '任务一', completed: false }]
    }, action) => {
        switch (action.type) {
            case 'addTodos':
                return {
                    ...state,
                    todos:[
                        ...state.todos,
                        {
                            id:Date.now(),
                            title:action.title,
                            completed: false
                        }
                    ]
                }
            default:
                return statereact
        }
    }
    const store = createStore(reducer);
    export default store;
    
    import {useDispatch} from "react-redux";
    const dispatch = useDispatch();
    dispatch({react
                type: 'addTodos',
                title: todo
            })
    

    react-redux提供了了两个api

    1. Provider 为后代组件提供store
    2. connect 为组件提供数据和变更更⽅方法
    import React from 'react'
    import ReactDom from 'react-dom'
    import App from './App'
    import store from './store/'
    import { Provider } from 'react-redux'
    ReactDom.render(
        <Provider store={store}>
        	<App/>
        </Provider>,
    	document.querySelector('#root')
    )
    
    import {connect} from "react-redux";
    export default connect(state => state)(App);
    

    或者

    import { useSelector } from 'react-redux'
    // useSelector 获取state
      const data = useSelector(state => state.data)
    // useDispatch获取dispatch
      const dispatch = useDispatch()
    

供数据和变更更⽅方法

import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
import store from './store/'
import { Provider } from 'react-redux'
ReactDom.render(
    <Provider store={store}>
    	<App/>
    </Provider>,
	document.querySelector('#root')
)
import {connect} from "react-redux";
export default connect(state => state)(App);

或者

import { useSelector } from 'react-redux'
// useSelector 获取state
  const data = useSelector(state => state.data)
// useDispatch获取dispatch
  const dispatch = useDispatch()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值