react知识概览

react原理

react->数据与模板相结合,生成虚拟dom,利用虚拟dom结构,生成真的dom。
如果数据改变,通过diff算法,比较原始的虚拟dom和新的虚拟dom,找出之间的区别,将差异的地方重新渲染。
减少对真实dom的创建和比对,提高性能

react虚拟Dom

const Dome = (
  <div class='container'>
    <span>直接写入html标签</span>
  </div>
)
关于虚拟dom
1.本质是object类型的对象
2.虚拟dom较轻,虚拟dom没有那么多属性
3.虚拟dom将被react转为真实dom,呈现在页面上

jsx语法规则

1.类名使用className
2.标签中插入js需要使用{}
1.标签首字母:大写->react按照组件去渲染,若组件未定义,将报错;小写->转为html同名标签渲染,若html无此标签报错。

组件定义

// 1.函数组件
function MyComponent(){
  return <div>函数组件</div>
}
// 2.类组件
class MyComponent extends React.Component{
  constructor(props){
    super(props);
    this.state = {};
  }
  render(){ return <div>类组件</div> }
}
// 组件渲染到app页面
ReactDom.render(<App/>, document.getElementById('container'));

组件状态states

class MyComponent extends React.Component{
  // 初始化状态简写
  /* state={age:25} */
  constructor(props){
    super(props);
    this.state = { // 初始化
      age:25
    };
  }
  render(){ return <div>类组件</div> }
}

组件属性props

1.组件的props,父级传给组件,不可以修改
2.组件的props限制
// 对标签属性的类型与必要性进行限制
class MyComponent extends React.Component{
  static propTypes = {
    name:PropTypes.string.isRequired, // 限制必传,字符串
    age:PropTypes.number, // 限制为数字
    eat:PropTypes.func // 限制为函数
  }
  // 传入默认属性
  static defaultProps = {
    sex:'男'
  }
  constructor(props){
    super(props);
  }
  render(){ return <div>类组件</div> }
}
// 函数组件
MyComponent.propTypes = {}
//指定默认标签属性值
MyComponent.defaultProps = {}

组件的ref

1.字符串  不推荐使用
2.回调函数  this指向的函数,比箭头回调函数少调用一次
3.creatRef  访问值需要在current中,this.myRef.current.value;
class Demo extends React.Component{
  myRef = React.createRef();
  showValue(){
    const { inputStr } = this.ref;
    console.log(inputStr.value);
    const { inputFunc } = this;
    console.log(inputFunc.value);
    console.log(this.myRef.current.value);
  }
  saveInput(ref){ // this指向的函数,比箭头回调函数少调用一次
    this.thisFuncRef = ref;
  }
  render(){
    return(
      <div>
        <input ref='inputStr' name='stringRef' /><br/>
        <input ref={ref=> this.inputFunc = ref} name='funcRef' /><br/>
        <input ref={this.saveInput} name='thisFuncRef' /><br/>
        <input ref={this.myRef} name='creat_Ref' />
        <button onClick={this.showValue} />
      </div>
    )
  }
}

组件中的事件处理

1.处理onXxx属性指定事件处理函数 
  例如onClick,onMousemove,onMouseover... 等等事件首字母需大写
  a.React使用的是自定义事件,非原生Dom事件---具有更好的兼容性
  b.React的事件均为事件委托方式处理(委托给组件最外层元素)---高效

收集表单数据

1.非受控组件->数据直接从ref中获取并提交
2.受控组件->数据存与state中,通过state获取数据并提交

组件的生命周期

生命周期图形

在这里插入图片描述

class MyDemo extends React.Component{
  constructor(props){ //构造函数执行单次 顺序1
    super(props);
  }
  componentWillMount(){
    console.log('即将挂载,执行单次 顺序2')
  }
  componentDidMount(){
    console.log('挂载完成,执行单次 顺序3')
  }
  componentWillUnmount(){
    console.log('即将卸载,执行单次')
  }
  componentWillReceiveProps(){
    console.log('即将收到父组件的props')
  }
  shouldComponentUpdate(){
    console.log('state更新,是否更新组件')
    return false;
  }
  componentWillUpdate(){
    console.log('组件将更新')
  }
  componentDidUpdate(){
    console.log('组件已更新')
  }
  render(){
    return(<div>生命周期</div>)
  }
}

Dom的diffing算法

1.虚拟Dom中key的作用
  当状态更新时,react会根据【新数据】生成【新的虚拟Dom】,React进行
  【新虚拟dom】与【旧虚拟dom】的diff比较:
  若旧虚拟dom找到与新虚拟dom相同的key:
    a.若未发生改变,则直接使用原来的dom
    b.若已发生改变,则生成新的真实dom,并替换于页面之中
  若未找到与新虚拟dom相同的key
    创建新的dom,渲染到页面
2.使用index作为key可能引发的问题
  a.若对数据进行逆序操作,会产生没有必要的更新,效率低下
  b.若结构包含输入类的dom,会产生错误的dom更新->界面出现问题

组件的一些事

1.两个子组件共同使用父级的state数据,通过props传递:状态提升
2.子组件->父组件,通过回调函数;父组件->子组件,props
3.defaultValue与value的区别,defaultValue为默认值
4.消息订阅与发布机制(组件通信)
import PubSub from 'pubsub-js'
// componentDidMount 订阅消息
this.token = PubSub.subscribe('xzp-go',function(title, data){
  // todo
});
// componentWillUnmount 取消订阅
PubSub.unsubscribe(this.token);
// 消息发送
PubSub.publish('xzp-go',{...data})

react路由

react靠路由连接实现组件切换
路由组件接收到Props不同:
  history:
    go: ƒ go(n) (页面跳转至n)
    goBack: ƒ goBack()  (返回上一级菜单)
    goForward: ƒ goForward()  (往前)
    push: ƒ push(path, state)
    replace: ƒ replace(path, state)
  location:
    pathname: "/about"
    search: ""
    state: undefined
  match:
    params: {} (参数传递)
    path: "/about"
    url: "/about"
路由的严格匹配与模糊匹配
  1.默认模糊匹配,【输入路径】必须包含【匹配的路径】,且顺序一致
  2.开启严格模式:<Route exact={true} path='/xxx' component={xxx} />
默认页面配置Redirect
  1.于所有路由最下方注册,当所有路由都匹配失败时,则跳转到Redirect指定的路由
嵌套路由
  1.注册子路由需要写上父级路由的path值
  2.路由的匹配是按照注册路由的顺序进行的
// 根组件
import { BrowserRouter } from 'react-router-dom';
ReactDom.render(<BrowserRouter><App/></BrowserRouter>, document.getElementById('root'));
// App
import { Link, Route } from 'react-router-dom';
<div className='link-list'>
  <Link className='link-item' to='/home'>Home</Link>
  <NavLink activeClassName='xzp-link' className='link-item' to='/xxx'></NavLink>
</div>
// Home为组件 提高匹配效率,路由命中后,将不再进行下一个路由的匹配
<div className='content-div'>
  <Switch>
    <Route path='/home' component={Home} />
    <Route path='/xxx' component={Home} />
    <Redirect to='/home' />
  </Switch>
</div>
//  子页面home
<NavLink to='/home/myCard'>myCard</NavLink>
<Switch>
  <Route path='/home/myCard' component={MyCard} />
</Switch>
// 路由组件传递state参数
<NavLink to={'/home/myCard/19970920/xzp'}>myCard</NavLink>
// 声明接收params参数
<Route path='/home/myCard/:id/:name' component={MyCard} />
// 路由组件获取参数
const { params = {} } = this.props.match || {};
// 路由组件传递search参数
<NavLink to={'/home/myCard/?id=19970920&name=xzp'}>myCard</NavLink>
// 路由不需要声明接收
// 路由组件获取参数
import qs from 'querystring'
const { search } = this.props.location || {};
const { id , name } = qs.parse(search.slice(1));
// 路由组件传递state参数
<Link to={{pathname:'/home/myCard',state:{id:19970920,name:'xzp'}}}>myCard</Link>
// 路由不需要声明接收
// 路由组件获取参数state
const { state={} } = this.props.location || {};
BrowserRouter与HashRouter的区别
1.底层原理不一致:
  browserRouter使用的是H5的history API,不兼容IE9及以下版本。
  hashRouter使用的是URL的哈希值
2.path表现形式不一样
  browserRouter -> localHost:3000/demo/test
  hashRouter -> localHost:3000/#/demo/test
3.刷新后对路由state参数的影响
  1.browserRouter无任何影响,state保存在history中
  2.hashRouter刷新后导致路由state参数丢失
4.hashRouter解决一些路径错误的相关错误

react redux react-redux

创建一个redux核心对象store
import { createStore } from 'redux';
import reducer from './xzp_reducer';
// 传入reducer
export default createStore(reducer);
reducer:本质为函数,传入两个参数:
preState:上一个state状态
action:dispatch发送过来的东西{type:xxx,data:xxx}
const initState = 0; // 初始化state
export default function xzpReducer(preState = initState, action){
  const { type, data } = action;
  switch(type){
    case 'xx': //todo 返回处理后的state
    case 'zz': //todo 返回处理后的state
    default: return preState;
  }
}
组件中调用:引入store,用于获取redux保存的状态
import store from './store';
store.dispatch({type:'add', data: {} });
新建文件:生成action对象
export const createAdd = data=>({type:'add',data});
export const createSub = data=>({type:'sub',data});
组件中调用:引入store,用于获取redux保存的状态
import store from './store';
import { createAdd } from './xzp_actions';
store.dispatch(createAdd(100));
异步action
1.需要使用中间件redux-thunk
2.创建action函数需要返回函数,该函数中写异步任务
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './xzp_reducer';
// 传入reducer
export default createStore(reducer, applyMiddleWare(thunk));
// 异步的action
export const createAsync = (data)=>{
  return (dispatch)=>{
    // todo something
    dispatch({type:'xxx', data})
  }
}
react-redux的使用,使用容器组件>UI组件,将state作为props传给UI组件
容器组件:将state与dispatch操作作为props传递给UI组件
/* 返回对象,对象中key作为传递给UI组件props的key,value作为传递给UI组件对应key的值 */
import { connect } from ' react-redux';
function mapStateToProps(state){
  return {keyName: state};
}
/* 返回对象,对象中key作为传递给UI组件props的key */
function mapDispatchToProps(dispatch){
  return {
    addValue:(val, name)=>{
      dispatch({type:'xxx',data:value});
    },
    asyncValue:(val)=>{
      dispatch(function(dp){
        dp({type:'add',value:val})
      });
    }
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(XzpUI);
// UI组件 获取value
const { keyName } = this.props;
// UI组件 调用dispatch操作
this.props.addValue(100);
react-redux优化给根组件包裹组件Provider
import store from './src/store';
import {Provider} from 'react-redux';
ReactDom.render(<Provider store={store}><App/></Provider>, document.getElementById('root'));
redux数据共享
  需要使用combineReducers对单个组件的reducer进行汇总
// store文件
import {createStore, applyMiddleware, combineReducers} from 'redux';
const allReducer = combineReducers({
  xzp:xzpReducer,
  yyy:yyyReducer
});
export default createStore(allReducer,applyMiddleware(thunk));
// 容器组件xzp示例
export default connect(state=>({
  name:state.xzp.name,
  love:state.yyy.name
}),dispatch=>({
  changeAge:(age)=>({type:'addAge',data:age})
}))(XzpUI);

redux redux-react总结

redux原理->发布式的监听器,创建存储空间store存储state,并提供发布功能来修改数据以及监听发布消息触发回调函数。
redux-react作用->监听store数据的变化,将数据传递给UI组件
  Provider->通过context api将store对象注入react组件
  Connect->高阶组件,监听store数据的更新,通过setState方法触发组件更新,并将state作为props传递给UI组件。

react扩展

setState

// 基础写法
this.setState({name:'xzp'});
// 对象式写法 setState为异步操作,完成修改后进入callback
this.setState({name:'yyy'},function(){
  // 状态修改、界面重新render后
});
// 函数式写法
this.setState((state, props)=>{
  return { name:'hh'};
}, function(){
  // 状态修改、界面重新render后
});

lazyLoad

import { lazy, Suspense } from 'react';
import Loading from './component/Loading';
const Home = lazy(()=> import('./component/Home'));
const Xzp = lazy(()=> import('./component/Xzp'));
<Suspense fallback={<Loading />}>
  <Route path='/home' component={Home} />
  <Route path='/xzp' component={Xzp} />
</Suspense>

Hooks

1.Hooks为react的新特性/新语法
2.可以在函数组件中使用state以及其他的react特性
useState 使用state
useEffect 生命周期钩子
useReducer -> dispatch
useMemo 缓存数据
useCallBack 缓存函数
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
function Demo(){
  // useState  0 赋值value, setValue
  const [value, setValue] = React.useState(0);
  const [name, setName] = React.useState('xzp');
  const myRef = React.useRef();
  // useEffect,useCallback,useMemo
  // 形参数组:监听改变数据,若改变则执行回调函数
  React.useEffect(()=>{
    // 组件挂载或监测数据改变,执行回调函数
    // 形参为undefined,监听所有的数据改变
    return ()=>{}// 相当于componentWillUnmont
  }, [name]);
  function changeAdd(){
    setValue(value +1);// 基础写法
    setValue((value)=>{ // 函数式写法
      return value +1;
    });
    // useRef的使用方法
    let inputValue = myRef.current.value;
  }
  const callback = useCallback(()=>{
    // 缓存函数执行内容,[]监听数据变化
  },[])
  const sum = useMemo(()=>{
    // 返回需要缓存的数据或者函数,[]监听数据变化
    let sum = 0;
    for (let i = 0; i < value * 100; i++) {
        sum += i;
    }
    return sum;
  },[])
  return (
    <div>
      <input type="text" ref={myRef} />
      <h2>state的值:{value}</h2>
      <button onClink={changeAdd}>+1</button>
    </div>
  )
}
/* useReducer */
const myReducer =(state, action)=>{
  switch(action.type){
    case 'xxx':
      // todo
      return {}
    default:
      return state;
  }
}
function App(){
  const [state, dispatch ] = useReducer(myReducer, {value:0})
  return (
    <div onClick={()=>{dispatch({type:'xxx',data:{}})}}>{state.value}</div>
  )
}

Fragment 与 空标签

区别:Fragment可以传key,空标签不可以新增任何属性

Context组件间通信方式

const MyContext = React.createContext();
const {Provider, Consumer} = MyContext;
let data = {name:'xzp'};
// 根组件调用
<Provider value={{data}}>
  <Root />
</Provider>
// 子类组件使用,必须声明,然后方可调用
static context = MyContext;
const {data = {}} = this.context;
// 子类组件(函数组件)
function Child(){
  return <div>
    <Consumer>
      {
        value=>{ return <span>{value.data.name}<span> }
      }
    </Consumer>
  </div>
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是React中常用的一些知识点: 1. 组件:React将用户界面拆分为可重用的组件,组件是构建React应用的基本单元。组件可以是函数组件或者类组件。 2. JSX:JSX是一种类似于HTML的语法扩展,可以在JavaScript代码中编写类似HTML的结构。它允许我们以声明式方式描述UI组件的结构。 3. Props:Props是组件的属性,用于传递数据和配置参数给组件。通过props,我们可以向子组件传递数据并进行组件之间的通信。 4. State:State是用于存储和管理组件内部的数据的对象。当state发生变化时,React会自动重新渲染组件,并更新相应的视图。 5. 生命周期:React组件具有生命周期方法,这些方法在组件的不同阶段被调用,例如组件被创建、更新、卸载等。 6. Hooks:Hooks是React 16.8版本引入的特性,它允许我们在无需编写类组件的情况下使用状态和其他React特性。常用的Hooks包括useState、useEffect、useContext等。 7. 条件渲染:React允许我们根据条件来渲染不同的内容或组件。常用的条件渲染方式包括if语句、三元表达式和逻辑与(&&)运算符等。 8. 列表渲染:React提供了map方法来遍历数组或者列表,动态生成列表项。通过列表渲染,我们可以根据数据动态生成多个相似的组件。 9. 表单处理:React提供了一些事件和处理函数来方便地处理表单的输入和提交。通过onChange事件,我们可以监听表单元素的值变化,并将其保存到组件的state中。 10. 组件通信:React中的组件通信可以通过props、状态提升、上下文(Context)和全局状态管理工具(如Redux)等方式来实现。 这些是React中常用的知识点,当然还有更多深入的内容和特性可以学习和掌握。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值