React开发遇到的问题

1. 引入图片出现404

  1. 在jsx中引入图片时,直接相对路径引入浏览器中运行会报404错误:使用require方法引入
    <img src={require(../../saaets/images/bg1.png)}/>

     

  2. 在css中使用背景图时,直接相对路径引入即可:
    body{
        background-image: url('../../asstes/images/bg1.png')
    }

     

2. 在使用ant组件中的input组件时,如果遇到传参则与vue中不同:

// vue中
<Input @change="change($event, 'name')"/>

// react中
<Input onChange={this.change.bind(this, 'name')}/>

在js中获取时:

// vue
change(argus) {
    const e = argus[0]
    const name = argus[1]
}

// react
changeValue (name, e) {
    console.log(name)
    console.log(e)
}

3. 使用路由时,获取不到this.props.history

// 在组件中引入
import { withRouter } from 'react-router-dom'

class Demo extends React.Components {
    ......
}

export default withRouter(Demo)

4. 使用redux的步骤

/*
    1. 首先在store文件夹中的module中划分模块,并在模块下建立一个js文件,如produxt.js
*/
import {createReducer} from 'redux-create-reducer'
import * as types from '../../../constants'

// 定义state
const state = {
	formData: {
        value1: '123'
    }
}

// 定义类型
const TYPES = {
	SAVE_FORM:`productOrder/${types.SAVE_FORM}`,
}

// Reducer
export const productOrder = createReducer(state, {
	[TYPES.SAVE_FORM]: (state,action) => {
        const {formData} = action.payload
        state.formData = formData
		return {
			...state
		}
	},
})

/*
    2. 在store下的index文件中引入,并注册
*/
import {combineReducers, applyMiddleware, compose, createStore} from 'redux'
import {connectRouter, routerMiddleware} from 'connected-react-router'
import {createBrowserHistory} from 'history'
import logger from 'redux-logger'
import {persistStore, persistReducer} from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

import privateRoute from './private-router'

// 加载store
import {productOrder} from './module/pages/product/product-order'

export const history = createBrowserHistory()
const persistConfig = {
	key: 'root',
	storage,
}

const createRootReducer = (history) => combineReducers({
	router: connectRouter(history),
	productOrder
})

// 从localstorage获取保存的数据
const preData = localStorage.getItem('persist:root')

const preSate = preData ? JSON.parse(preData) : {}
for (let e in preSate) {
	preSate[e] = JSON.parse(preSate[e])
}

// 替换键名为对应的Reducer名
if (preSate.router) delete preSate.router

const store = createStore(
	persistReducer(persistConfig, createRootReducer(history)),
	preSate,
	compose(
		applyMiddleware(
			routerMiddleware(history), // for dispatching history actions
			privateRoute,
			logger
		)
	))
export default store
export const persistor = persistStore(store)

/*
    3. 在组件中使用时要注意connect,使用form表单时注意Form.create
*/
const ProductForm = Form.create({
    mapPropsToFields(props) {
        let {formData} = props
        const formKeys = Object.keys(formData)
        const fields = {}
        forEach(formKeys,item=>{
            fields[item] = Form.createFormField({
                value: formData[item],
            })
        })
        return fields
    },
    onFieldsChange(props, changedFields) {
        console.log(changedFields)
    },
    // 表单内输入框变化时
    onValuesChange(_, values) {
        console.log(values)
    }
})(ProductOrder)

function mapStateToProps(state) {
    const {formData} = state.productOrder
    return {formData}
}

function mapDispatchToProps(dispatch) {
    return {
        saveUser:(data) => dispatch({type:'user/INCREMENT', payload:data})
    }
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductForm))

5. 使用redux存储数据,页面刷新后数据丢失:采用redux-persist

// 在store的入口文件引入redux-persist
import { createStore, applyMiddleware, compose } from 'redux';
import { createLogger } from 'redux-logger';
import thunk from 'redux-thunk';
import reducers from './reducers/index';
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const loggerMiddleware = createLogger();
const persistConfig = {
    key: 'root',
    storage: storage,
    // stateReconciler: autoMergeLevel2 // 查看 'Merge Process' 部分的具体情况
};

const myPersistReducer = persistReducer(persistConfig, reducers)
const store = createStore(myPersistReducer)
export const persistor = persistStore(store)
export default store;

// 在项目的入口文件index.js中做如下修改
import React from 'react';
import ReactDOM from 'react-dom';
import axios from '@/axios/$axios';
import App from './App';
import * as serviceWorker from './serviceWorker';

import {Provider} from 'react-redux'
import store from './redux/store'
import {persistor} from './redux/store'
import {PersistGate} from 'redux-persist/integration/react';

// ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render(<Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
        <App />
    </PersistGate>
</Provider>, document.getElementById('root'));

6. table中的分页配置

<Table
	columns={this.props.columns}
	dataSource={this.props.dataSource}
	rowKey={record => record.id}
	bordered={true}
	loading={this.props.loading}
    size="small"
    pagination={{
        total: this.props.total,
        pageSizeOptions: [10, 20, 30, 40, 50],
        showSizeChanger: true,
        showTotal: () =>{
            return `共 ${this.props.total} 条`;
        },
        onChange: (page, pageSize) => {
            this.props.onSizeChange(page, pageSize)
        },
        onShowSizeChange: (current, size) => {
            this.props.onShowSizeChange(current, size)
        },
     }}/>

7. ant-design中表达如何赋值:

componentDidMount() {
	// 表单赋值
	let {form} = this.props
	Object.keys(form.getFieldsValue()).forEach(key => {
		const obj = {};
		obj[key] = 1;
		form.setFieldsValue(obj);
	});
}

8. getFieldDecorator` will override `value`, so please don't set `value` directly and use `setFieldsValue` to set it.:不要直接给组件绑定value值了。

9. 在react项目中引入动画组件react-transition-group后,组件挂载执行两次,在componentDidMount中的请求接口连续两次。

================================================================================================

10. 配置按需加载时,运行npm run eject 报错This git repository has untracked files or uncommitted changes解决方案,按需加载配置过程参考:https://www.jianshu.com/p/46b099c1107a

1.初始化仓库
git init
 
2.添加并提交
git add .
git commit -m 'init project'
 
3.重新执行 npm run eject

11. 在使用ant-design-mobile定制主题时

// 1. 在项目根目录下建一个config-overrides.js文件,并安装"customize-cra"和"react-app-rewired"
const { override, fixBabelImports , addLessLoader} = require("customize-cra");
const theme = require('./antd-theme');
module.exports = override(
  addLessLoader({
    lessOptions: {
        javascriptEnabled: true,
        modifyVars: theme
    }
  }),
  fixBabelImports("import", {
        libraryName: "antd-mobile",
        libraryDirectory: 'es',
        style: true,
    }),
);

// 2. 在package.json中将scripts修改为
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test"
}

12. 在进行 react 项目开发的时候,出现了这个错误,ValidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the API schema.这个实际上是 Less Loader 的版本导致的兼容性问题,需要更换 Less Loader 的版本,把 Less Loader 进行降级,通过 npm remove less-loader命令卸载 Less Loader ,通过 npm i less-loader@5.0.0 命令安装 less-loader@5.0.0 的版本,然后问题就可以解决了。

13. react路由配置---react-router-dom参考:https://blog.csdn.net/liushijun_/article/details/94907262

*react中key的作用:标识了当前层级下节点的唯一性,判断节点能不能复用的前提是key和type;

*component与pureComponent的区别:pureComponent内置了一个生命周期(shoudComponentUpdate)自动比较state或者props有没有发证变化,但是是浅比较,

*diff算法,只有同一层级下key和type一致时才会复用;没有给默认的key时,用下标标识;

* 函数柯里化: 在一个函数中首先填充几个函数  在返回一个新的函数的的技术叫做函数柯里化

* 闭包: 可以访问自身作用域 父级作用域 父级函数参数作用域 直至找到全局作用域的函数叫做闭包

* 高阶函数:将函数作为参数或返回值的函数

* es6: 箭头函数 类 promise 生成器 块级作用域 set 对象解构 rest set 模板字符串

* redux: 全局唯一的数据源 store  可以通过 getState 拿到state 一个view对应一个state,state 的变化会导致view更新   但是用户拿不到state  只能通过view触发action来改变state
* action 是一个对象  必选包含 tpye 属性   store。dispatch() 是view触发action的唯一方法   store 接收到action事件后, 必须给一个新的state 然后view根据state发生变化 这种计算过程叫 reducer  reducer 是一个纯函数  接收action和state作为参数  返回一个新的state
>* react 生命周期  挂载  渲染  卸载
* constructor 接收两个函数 props 和 context 使用 constructor 必须使用 super() this 指向
* componentWillMonut 一般用于服务端渲染
* componentDidMount 初次渲染 ajax 请求
* componentWillUnmount  组件卸载  清楚定时器  事件绑定
* componentWillReceiveProps 接收父组件改变后的props需要重新渲染组件的时候使用
* shouldComponentUpdate 用于优化控制组件重新渲染的生命周期 return false 可以阻止渲染
* componentDidUpdate 组件更新完毕
* render 插入 jsx 生成的虚拟dom  根据 diff 算法比对后进行渲染
* key 的作用 性能优化 diff算法会根据key进行比对 没有重新插入  有的话不会重新创建

> setState 异步  保持 state props refs 一致性   批量处理 多次合并成一次 优化性能

> react 组件传值
>* 父传子 props  
>* 子传父 子调用父的方法传参
>* 兄弟传值  发布订阅模式

> http 和 https 的区别
>- http 使用80端口 https 使用 443 端口
>- https 比 http 要慢,因为HTTPS除了TCP握手的三个包,还要加上SSL握手的九个包
>- HTTP是超文本传输协议,是明文传输;HTTPS是经过SSL加密的协议,传输更安全
>- HTTPS需要申请证书

> HTTP2 四个新特性:
>- 多路复用,无需多个TCP连接,因为其允许在单一的HTTP2连接上发起多重请求,因此可以不用依赖建立多个TCP连接。
>- 二进制分帧,将所有要传输的消息采用二进制编码,并且会将信息分割为更小的消息块。
>- 头部压缩,用HPACK技术压缩头部,减小报文大小
>- 服务端推送,服务端可以在客户端发起请求前发送数据,换句话说,服务端可以对客户端的一个请求发送多个相应,并且资源可以正常缓存。

> 资源预加载
>* preload 页面加载过程中,在浏览器开始主体渲染之前加载
>* prefetch 页面加载后, 利用空余时间提前加载

> 浏览器渲染过程
>* 将获取到的html解析成 dom tree
>* 处理css  生成 cssom tree
>* 将DOM和CSSOM合并为渲染树(rendering tree),代表一系列将被渲染的对象。

>* 缓存
>   缓存机制 强缓存优先于协商缓存 若强缓存生效则直接使用强缓存 否则使用协商缓存 协商缓存由服务器决定是否使用缓存 若协商缓存失效则返回 200 重新返回资源和缓存标识 在存入浏览器缓存中 生效则返回 304  继续使用缓存
>  Service Worker  必须是 https  然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。
>  强缓存 200 不会请求数据  直接从缓存中获取 header 中的Expires 和 Cache-Control 设置
>   协商缓存 304 查看本地缓存是否失效 携带缓存标示向服务器发起请求 由服务器根据缓存标识决定是否使用缓存 HTTP Header 实现:Last-Modified 和 ETag 。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值