生命周期函数、redux的使用(一)

2024-03-14 19:48

本文主要是介绍生命周期函数、redux的使用(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在定义React组件的时候,render()函数返回的html必须只有一个根元素,要想这个根元素不显示并且不占据页面空间,可以从react中引进Fragment组件

 

JSX语法细节

在JSX里面写注释的方法:

多行注释:
{/*注释注释*/}单行注释:
{
//注释注释
}

属性:dangerouslySetInnerHTML={{_html: item}}可以让内容item不转义,直接显示

属性class写成className属性for写成htmlFor

 

<lable  htmlFor='inputId'></lable>标签用于扩大输入框的范围,点击文字的时候,光标定位到input输入框

<input  id='inputId'/>

 

PropTypes与DefaultProps的应用

PropTypes接受组件传过来的参数时,对参数类型做校验

通过下面的语句引进PropTypes,通过脚手架create-react-app已经有prop-types包,所以可以直接引进

import PropTypes from 'prop-types';
class TabNav extends Component{//强制设置变量的类型static propTypes = {val: PropTypes.string。isRequired,activeIndex: PropTypes.number,//可以是数字也可以是字符串text: PropTypes.arrayOf(PropTypes.number,PropTypes.string)};
}

defaultProps即对组件接收的参数赋予默认值,如果父组件没有给子组件传递该参数的值,则子组件使用默认值

 

state、props与render()函数的关系

当state、props中的属性的值发生变化的时候,render()函数重新执行,即当数据一变,就会调用render()函数,重新渲染页面,从而改变页面,达到数据一变,页面就会变

子组件的render()调用时机:当子组件的props或者state属性发生变化时调用render()函数,或者父组件的render()调用时,子组件的render()会调用

 

虚拟DOM------就是一个JS对象,用来描述真实的DOM

在React中,虚拟DOM的操作不怎么耗性能,实际是操作真实的DOM比较耗性能,比较新旧虚拟DOM的差异(使用diff算法),找到差异的地方,直接更新变化的DOM

虚拟DOM的优点:

1)性能提升,真实DOM的比对变成虚拟DOM的比对

2)它使得跨端应用得以实现。React Native

虚拟 DOM中的diff:同层比较,在用列表表示的时候,key的值最好不用index,使得不变的元素的新旧key值一样,从而提升性能

setState(对象/异步func(prevState),func---当第一个异步函数操作完之后就执行该函数):异步函数是为了将多次间隔较短的虚拟DOM的变化,合并成一次虚拟DOM的变化,提高性能

 

JXS中的tag中的属性ref的值是一个函数,用于获取DOM,但在实际中不推荐使用该属性获取该元素,因为React中是数据驱动,不推荐直接操作DOM 

 

React中的生命周期函数---指在某一时刻会自动执行的函数

initialization---组件初始化

setup props and state

 mounting----组件挂载(只执行一次)

//执行顺序
//1、在组件即将被挂载到页面的时候执行
componentWillMount(){console.log(1)
}//2、将JSX模板渲染成真实的DOM
render(){}//3、在组件挂载到页面之后调用
componentDidMount(){}

updation---组件更新(数据发生变化,props   state)

//props发生变化的时候,即数据发生变化,导致组件的更新,触发下面的过程//1、一个组件要从父组件接受参数,只要父组件的render函数重新被执行了,子组件的这个生命周期函数就会被执行----也就是说这个组件第一次存在于父组件不会执行,如果这个组件之前存在于父组件中,才会执行
componentWillReceiveProps(){}//2、组件在更新之前,自动调用,返回boolean类型值,决定是否更新组件
shouldComponentUpdate(){return true
}//3、
componentWillUpdate(){}//4、
render(){}//5、
componentDidUpdate(){}
//state中的属性发生变化的时候,触发下面的函数
//1、
shouldComponentUpdate(){}//2、
componentWillUpdate(){}//3、
render(){}//4、
componentDidUpdate(){}

unmounting---组件卸载

//组件卸载之前执行
componentWillUnmount(){}

shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?)

shouldComponentUpdate 的返回值是boolean类型,用来判断是否需要调用 render 方法重新描绘 dom(返回true值)。

因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能

 

 

 

生命周期函数的使用场景

在定义组件的时候,一定要书写render()函数,因为React内置了除了render()函数之外的所有生命周期函数

1)ajax请求放在componentDidMount()中,该函数只执行一次

 

使用charles实现本地数据mock,使用axios方法

 

使用css的transition,animation实现简单动画,或者使用react第三方插件react-transition-group实现用js实现的动画

  <CSSTransition{/*showValidationMessage在state中定义,为boolean类型,当由true->false或者false->true发生一些动画*/}in={this.state.showValidationMessage}{/*动画执行的时间*/}timeout={300}{在.css文件中定义的类名的前缀,如fade-enter,fade-enter-active}classNames="fade"//当元素被隐藏的时候,DOM被移除unmountOnExit//退出时的函数onExited={() => {this.setState({showValidationButton: true,});}}//当页面刚开始的时候也使用样式appear={true}>

<CSSTransition>组件实现单个组件的动画

<TransitionGroup> + <CSSTransition>实现多个组件的动画

 

 

React是一个简单的视图层框架

Redux = Reducer + Flux:是一个数据层框架,主要方法是createStore(redux)和store.dispatch(action),store.subscribe(event)

Flux是一个辅助React的数据层框架:存在的问题是可以有很多个store,造成数据存储存在依赖的问题

有了Redux之后,将组件的数据存储在Store里面,当组件的数据发生变化,Store里面的数据发生变化,然后接着改变其他组件的数据

 

Antd(用于快速构建后台界面用的,前端UI用的较少)或者、semantic-ui-react是用于构建React UI 的插件

 

首先在项目中安装redux,redux在chrom中的调试插件redux devtools

创建reducer

1)在src/store/reducer.js文件里面定义reducer(相当于一个记录本,里面定义state的默认值,然后必须返回一个函数)

const defaultState = {inputVal: '123',list: [1,2]
}//state是整个store里面的数据
export default (state = defaultState, action) => {return state;
}

2)在src/store/index.js文件里面定义store

//该方法用于创建store对象
import { createStore } from 'redux';
//导进reducer(记录本)
import reducer from './reducer';
const store = createStore(reducer);export default store;

3)component连接store

//在component中引进store
import store from './store/index.js'
class TodoList extends Component{constructor(props){super(props);//利用store提供的getState()方法拿到store中的state数据this.state = store.getState() ;}
}

4)在浏览器中安装调试redux的插件redux devtools,然后在组件中需要进行如下配置

在创建store的地方进行如下配置

//该方法用于创建store对象
import { createStore } from 'redux';
//导进reducer(记录本)
import reducer from './reducer';
const store = createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);export default store;

5)在React Component中定义action,并且将action分发给store对象

//在TodoList组件里面定义action
//在输入框中定义事件change
<input onChange={this.handleInputChange}>handleInputChange(e){//创建action//input(React Component)框告诉store要做的action(Action Creators)const action={type:'change_input_value',//可以将input的value传递过去value:e.target.value}//组件将action传给store对象store.dispatch(action);
}

6)store接收到action之后,自动将接收到的action和store中之前的数据传给reducer,这时候需要在reducer里面根据action做相应的处理,将处理完之后的newState返回给store 对象

const defaultState = {inputVal: '123',list: [1,2]
}//state是整个store里面的数据
// reducer可以接收state,但不能直接修改state
export default (state = defaultState, action) => {//根据action做相应的处理if( action.type === 'change_input_value' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//对公共数据的修改newState.inputVal = action.value// 将数据返回给store对象return newState}return state;
}

7)store接收到reducer处理之后返回的newState。这时候需要用newState替换掉component中的state数据

利用store.subscribe(event)订阅一个事件event,event用于更新component中的state数据

//在component中引进store
import store from './store/index.js'
class TodoList extends Component{constructor(props){super(props);//利用store提供的getState()方法拿到store中的state数据this.state = store.getState() ;// 在组件中订阅store对象的事件,store中数据发生变化,就自动执行该函数this.handleStoreChange = this.handleStoreChange.bind(this)store.subscribe(this.handleStoreChange);}handleStoreChange(){// 当组件感知store中的数据发生变化的时候,从store中// 拿到newState,然后替换掉当前组件的state数据,达到this.setState(store.getState())}
}

8)component中的state数据更新了,现在需要点击按钮时,将新增的数据添加到数组里面,而现在所有的数据都放到了store对象里面,即点击按钮的时候,需要改变的是store对象中的数据

在组件上面定义事件,在事件里面定义action,并通过store.dispatch(action)传递给store对象

// 在Button组件上绑定事件
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>// 在组件上定义action,并且通过store.dispach(action)将action分发给store对象
handleBtnClick() {// action对象必须有type属性,// 剩余的要对应上在reducer中定义的属性名const action = {type: 'add_todo_item'}// 将action传递给storestore.dispatch(action)
}

9)store对象接收到action,就自动触发reducer根据action做相应的处理,处理完后将newState返回给store对象

const defaultState = {inputVal: '123',list: [1,2]
}//state是整个store里面的数据
// reducer可以接收state,但不能直接修改state
export default (state = defaultState, action) => {//根据action做相应的处理if( action.type === 'change_input_value' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//对公共数据的修改newState.inputVal = action.value// 将数据返回给store对象return newState}//根据action做相应的处理if( action.type === 'add_todo_item' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//对公共数据的修改newState.list.push(newState.inputVal)// 将数据清空newState.inputVal = ''// 将数据返回给store对象return newState}return state;
}

10)store对象接收到newState,由于之前在component中的constructor中已经订阅事件store.subscribe(this.handleStoreChange);通过handleStoreChange修改组件的state,所以已经达到点击按钮,向数组添加数据的目的

 

点击具体的item的时候将其删除掉

1)在组件上面绑定事件,并且向事件传递index参数

<List.Item onClick={this.handleItemDel.bind(this,index)}>{item}</List.item>

2)在事件里面定义action,通过store.dispatch(action),将动作传递给store对象

handleItemDel(index){const action={type:'delete_todo_item',index}store.dispatch(action)
}

3)此时store接收到action,并将store中的state和action一起传给reducer,reducer执行相应的action,返回newState给store对象,由于之前在component的constructor中通过store.subscribe(event),在event中通过store.getState()重新对component的state赋值,达到删除功能

const defaultState = {inputVal: '123',list: [1,2]
}//state是整个store里面的数据
// reducer可以接收state,但不能直接修改state
export default (state = defaultState, action) => {//根据action做相应的处理if( action.type === 'change_input_value' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//对公共数据的修改newState.inputVal = action.value// 将数据返回给store对象return newState}//根据action做相应的处理if( action.type === 'add_todo_item' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//对公共数据的修改newState.list.push(newState.inputVal)// 将数据清空newState.inputVal = ''// 将数据返回给store对象return newState}//根据action做相应的处理if( action.type === 'delete_todo_item' ){//对数据作一个深拷贝const newState = JSON.parse(JSON.stringify(state))//删除对应下标的数据newState.list.splice(action.index,1)// 将数据清空newState.inputVal = ''// 将数据返回给store对象return newState}return state;
}

 

ActionTypes的拆分

解决的问题:当action.type拼写错误,但在浏览器没有报错也没有提示任何信息,为了解决这个问题将ActionTypes在一个文件夹里面定义成常量,然后输出。当书写错误的时候,浏览器会报错

1)在src/store下新建文件actionTypes.js,内容如下

const CHANGE_INPUT_VALUE = 'change_input_value',ADD_TODO_ITEM = 'add_todo_item',DELETE_TODO_ITEM = 'delete_todo_item'
export {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM
}

2)在组件里面引进该对象,然后将action里面的type换成上述文件定义成的常量变量

同时在reducer中将action.type也换成定义的常量变量

 

使用actionCreator统一创建action,便于管理,提高代码的可读性,便于自动化测试

1)在src/store下面创建文件actionCreators.js

import {CHANGE_INPUT_VALUE} from './actionTypes'// actionCreator,返回一个action对象
const getInputChangeAction = (value) => {type: CHANGE_INPUT_VALUE,value
}export { getInputChangeAction }

 

2)在组件引入action

import {getInputChangeAction} from './store/actionCreators.js'

3)在组件中使用action

//在TodoList组件里面定义action
//在输入框中定义事件change
<input onChange={this.handleInputChange}>handleInputChange(e){//创建action//input(React Component)框告诉store要做的action(Action Creators)const action = getInputChangeAction(e.target.value)//组件将action传给store对象store.dispatch(action);
}

redux的3个基本原则

1)store对象必须是唯一的,在src/store/index.js中定义

2)只有store能够改变自己的内容(reducer根据action进行相应操作后,将newState返回给store,store将自己的内容更新,所以不能在reducer里面直接修改state的内容)

3)reducer必须是纯函数(固定输入,固定输出,并且不会有任何副作用---例如不会修改传入参数的值)

 

redux的核心API

createStore(reducer)------创建store
store.dispatch(action)----组件向store传递action
store.subscribe(event)----向store订阅事件,只要store内容一变,就触发event
store.getState()----------拿到store里面的内容

 

UI组件(展示型组件)与容器型组件的拆分

UI组件负责页面的展示,数据通过容器型组件传过来,通过props拿到数据;在TodoListUI.js里面只有render()函数里面直接返回JSX;

容器性组件TodoList.js负责页面的逻辑

 

Redux中发送异步请求获取数据----

在componentDidMount()中发送ajax请求,拿到数据后给store传递action

 1)在项目中安装axios插件

2)在容器型组件中引进axios

3)在componentDidMount()中定义action,并将action传递给store

componentDidMount(){axios.get('/list.json').then((res)=>{const data = res.data// 创建actionconst action = initListAction(data)store.dispatch(action)}).catch(e){console.log(e)}
}

接着在reducer中根据action.type进行操作

 

 

发使用redux-thunk中间件实现ajax数据请求

--------为了将异步请求和复杂的逻辑抽取出来,将代码放到一个统一的文件,便于统一管理

redux-thunk中间件可以把异步请求和复杂的逻辑放到action里面处理

在项目中安装redux-thunk,根据官网例子书写代码   https://github.com/reduxjs/redux-thunk    链接

1、在创建store对象的index.js文件做如下修改:对redux-thunk进行配置
 

// 该方法用于创建store对象
// 引进方法 applyMiddleware,才能使用中间件
import { createStore,applyMiddleware,compose } from 'redux';
//导进reducer(记录本)
import reducer from './reducer';
import thunk from 'redux-thunk';const composeEnhancers =  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;const enhancer = composeEnhancers(applyMiddleware(thunk),// other store enhancers if any
);// 在创建stor的时候,使用reducer构建初始的数据,
// 在创建store的时候会使用中间件redux-thunk
const store = createStore(reducer,enhancer
);export default store;

2、对redux-thunk进行配置好后,可以将异步操作放到action里面进行操作

在src/store下面创建文件actionCreators.js中使用了中间件redux-thunk,那么创建的action可以返回函数,而不仅仅是返回一个对象,在返回的函数里面进行异步操作

import {CHANGE_INPUT_VALUE} from './actionTypes'
import axios from 'axios'// actionCreator,返回一个action对象
const getInputChangeAction = (value) => {type: CHANGE_INPUT_VALUE,value
}// 使用Redux-thunk中间件之后,创建的action可以返回一个函数,当store接受
// 到这个action时,action的函数会自动执行
const getTodoList = () =>{return (dispatch) => {// 异步请求拿到数据axios.get('/list.json').then((res)=>{const data = res.data;//改变store里面的数据const action = initListAction(data);dispatch(action)})}
}export { getInputChangeAction, getTodoList }

3、在组件的componentDIdMount()中调用上述函数,从而得到action

import { getTodoList } from 'actionCreators.js'componentDIdMount(){// action是一个函数const action = getTodoList();// 执行action函数store.dispatch(action)
}

 

redux中间件---处理异步事件

redux中间件指的是Action和Store之间的中间件

中间件指的是对dispatch方法的升级,使得该函数的参数除了是对象之外还可以是函数

可以用redux-thunk对dispatch升级

 

Redux-saga中间件-----处理异步代码,在redux-saga里面会将一些异步代码放到单独文件里面

用了Redux-saga中间件,除了在reducer中接收action,还可以在saga文件中接收action

1)将Redux-saga插件安装到项目里面,https://github.com/redux-saga/redux-saga  链接

2)在src/store下创建sagas.js文件,用于存放异步代码

// saga必须使用generator
import { takeEvery,put } from 'redux-saga/effects'
import {GET_INIT_LIST} from './actionTypes'
import {initListAction} from './actionCreators'
import axios from 'axios'function* getInitList(){// 处理请求失败的结果try{const res = yield axios.get('/list.json')const data = res.dataconst action = initListAction(data)// 将action传递给storeyield put(action)}catch(e){console.log('list.json网络请求失败')}}function* mySaga() {// 获取每一个 actionyield takeEvery(GET_INIT_LIST, getInitList);
}export default mySaga;

 

 

3)在创建store对象的文件里面进行如下配置,src/store/index.js

// 该方法用于创建store对象
// 引进方法 applyMiddleware,才能使用中间件
import { createStore,applyMiddleware,compose } from 'redux';
//导进reducer(记录本)
import reducer from './reducer';
//存放异步代码
import mySaga from  './sagas'
// 创建中间件的方法
import createSagaMiddleware from 'redux-saga';
// create the saga middleware
const sagaMiddleware = createSagaMiddleware();const composeEnhancers =  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));// 在创建stor的时候,使用reducer构建初始的数据,
// 在创建store的时候会使用中间件redux-thunk
const store = createStore(reducer,enhancer
);
// then run the saga
sagaMiddleware.run( mySaga);
export default store;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4)在src/store/actionTypes.js中定义常量

export const GET_INIT_LIST = 'get_init_list'

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

5)在创建action的文件src/store/actionCreators.js里面创建action,这个action返回的是对象

import {GET_INIT_LIST} from './actionTypes.js'
export const getInitList = ()=>({type:GET_INIT_LIST})

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

6)在组件生命周期里面调用

componentDidMount(){const action = getInitList()store.dispatch(action)
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

React-redux的使用

通过以下步骤创建了store,reducer,并且组件和store建立连接:

1)在项目中安装react-redux

2)在src/TodoList.js书写组件的内容,创建store,reducer对象之后,在component组件文件里面引进store对象之后,通过store.getState()拿到store的数据,从而让store和component 建立连接

import React,{Component} from 'react'
import store from './store'
class TodoList extends Component{constructor(props){super(props)// 获取store对象的数据初始化statethis.state = store.getState()}render(){return (<div><div><input value={this.state.inputValue}/><button> </button><div/><ul><li>dell</li></ul></div>)}
}
export default TodoList

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3)在src/index.js中引进组件

import React from 'react'
import ReactDOM from 'react-dom'
import TodoList from './TodoList'
ReactDOM.render(<TodoList />,document.getElementById('root'))

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4)在src/store/reducer.js下创建reducer,该文件返回纯函数,以及定义初始化state的数据

const defaultState = {inputValue:'',list:[]
};
export default (state=defaultState,action) => {return state
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

5)所有的数据放在store里面,在src/store/index.js下创建store对象

import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

在React中使用Redux:
1)在src/index.js文件中使用React-redux的组件<Provider store={store}>这样使得组件Provider的子元素可以获取到store的内容

store与子component建立连接

import React from 'react'
import ReactDOM from 'react-dom'
import TodoList from './TodoList'
// 引进React-redux中的 组件
import {Provider} from 'react-redux'
import store from './store'
const App = (// Provider连接了store,那么Provider的所有子元素可以获取到store内容<Provider store={store}><TodoList /></Provider>
)
ReactDOM.render(App,document.getElementById('root'))

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2)在子组件中通过connect()使store和子组件建立连接,并且将store中的state映射到props,同时通过props修改store中的内容

import React,{Component} from 'react'
import store from './store'
import {connect} from 'react-redux'
class TodoList extends Component{constructor(props){super(props)// 获取store对象的数据初始化statethis.state = store.getState()}render(){return (<div><div>{/*这是因为将state映射成props*/}<input value={this.props.inputValue} onChange={this.props.changeInputValue}/><button onClick={this.props.handleClick}> </button><div/><ul><li>dell</li></ul></div>)}}// 就是将store里面的公用数据映射成props
const mapStateToProps = (state)=>{return {inputValue:state.inputValue}
}// 通过props修改store的内容
// 让store.dispatch挂载到props上
const mapDispatchToProps = (dispatch) => {return {changeInputValue(e){const action = {type:'change_input_value',value:e.target.value}// 修改store的内容dispatch(action)},handleClick(){const action ={type:'add_item'}}dispatch(action)}
}// 让子组件TodoList和store建立连接
//通过mapStateToProps,store里面的state会映射成组件的props
export default connect(mapStateToProps,mapDispatchToProps)(TodoList)

3)通过上面配置,将action通过dispatch到store,并传给reducer,在reducer中需要根据action.type进行相应处理

const defaultState = {inputValue:'',list:[]
};
export default (state=defaultState,action) => {if( action.type === 'change_input_value' ){const newState = JSON.parse(JSON.stringify(state))newState.inputValue = action.valuereturn newState}if( action.type === 'add_item' ){const newState = JSON.parse(JSON.stringify(state))newState.list.push(newState.inputValue)newState.inputValue = ''return newState}return state
}

改进后的组件:

import React,{Component} from 'react'
import store from './store'
import {connect} from 'react-redux'// UI组件,无状态组件---提升性能,无生命周期函数,只是进行展示,从props中拿数据
const TodoList = (props)=>{const { inputValue,changeInputValue, handleClick } = propsreturn (<div><div>{/*这是因为将state映射成props*/}<input value={inputValue} onChange={changeInputValue}/><button onClick={handleClick}> </button><div/><ul>{this.props.list.map((item,index)=>{return <li key={index} onClick={handleDelete}>{item}</li>})}</ul></div>)
}// 就是将store里面的公用数据映射成props
const mapStateToProps = (state)=>{return {inputValue: state.inputValue,list: state.list}
}// 通过props修改store的内容
// 让store.dispatch挂载到props上
const mapDispatchToProps = (dispatch) => {return {changeInputValue(e){const action = {type:'change_input_value',value:e.target.value}// 修改store的内容dispatch(action)},handleClick(){const action ={type:'add_item'}dispatch(action)},handleDelete(index){const action ={type:'delete_item',index}dispatch(action)}}
}// 让子组件TodoList和store建立连接
//通过mapStateToProps,store里面的state会映射成组件的props
// connect()输出的结果是容器组件,因为将数据和逻辑与UI组件进行结合就是容器组件
export default connect(mapStateToProps,mapDispatchToProps)(TodoList)

 

Styled-Components的使用----让组件的样式只对组件的样式生效,不会在全局中生效,在标签上直接书写css然后输出该组件

问题:在src目录下有文件index.js    index.css  App.js,在文件index.js引进index.css,但没有在App.js里面引进index.css,也可以使用在index.css里面的类--------在React中引进css,将会在全局中生效,就会造成组件中的类冲突

解决方法:使用第三方插件---styled-components

styled-components的定义

styled-components 是一个常用的 css in js 类库,和所有同类型的类库一样,通过 js 解决了原生 css 所不具备的能力,比如变量、循环、函数等

styled-components比其他css预处理器的优点

  • 诸如 sass&less 等预处理可以解决部分 css 的局限性,但还是要学习新的语法,而且需要对其编译,需要复杂的 webpack 配置
  • 如果有过sass&less的经验,也能很快的切换到styled-components,因为大部分语法都类似,比如嵌套,& 继承等, styled-componens 很好的解决了学习成本与开发环境问题,很适合 React 技术栈 && React Native 的项目开发

styled-components解决的问题

  • className 的写法会让原本写css的写法十分难以接受
  • 如果通过导入css的方式 会导致变量泄露成为全局 需要配置webpack让其模块化
  • 以及上面提到的解决了原生 css 所不具备的能力,能够加速项目的快速开发

转载出处:https://www.jianshu.com/p/2178abb2ee95  

 

1、在项目中安装styled-components,不需要在文件中引进,但是将.css文件改成.style.js文件

2、全局样式injectClobal被createGlobalStyle替代,用组件的方式渲染,具体使用

3、将css reset的代码复制到createGlobalStyle里面----让默认样式在所有浏览器表现一致

 

 

使用iconfont嵌入头部图标

官网  https://www.iconfont.cn/

1、登录iconfont,在“图标管理”下选择“我的项目”,点击右边“新建项目”的图标

2、在主页的搜索框中输入要查找的图标名,然后选择要的图表,选择“添加入库”

3、所有图表选择好之后,点击右上角的“购物车”图标,点击“添加至项目”

4、然后点击“下载至本地”

5、然后将压缩包解压缩,将文件iconfont.eot       iconfont.svg      iconfont .ttf       iconfont .woff文件复制到项目的src/static/iconfont文件夹下面

6、在项目中使用 iconfont,首先需要想修改文件iconfont.css里面的内容:将路径以iconfont开头的路径改成相对路径

@font-face {font-family: "iconfont";src: url('./iconfont.eot?t=1551963575525'); /* IE9 */src: url('./iconfont.eot?t=1551963575525#iefix') format('embedded-opentype'), /* IE6-IE8 */url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPQAAsAAAAAB9gAAAOCAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqDFIJ7ATYCJAMQCwoABCAFhG0HRxvsBsgeh+kWI3+SnJzkPR6+v0/Pff9m3SxAmWAAMx7gZW3HK9aKFmtWXnaB/F9b+gfYhA51IebGpvWVYUUfO3VRUveT+E30FGkCBID6xL3Tpm2w+SzLaaxFa9P/3EVdgPHWwPbENmUFWiAJesvwapfCQR8mgLaBwqF1YXk98DhkVABxbzHpgM84cQ3kwEO8KhYmoCfQ4Mt85gGAx+D78Q+x8QCFpgIycXMsMEL2l//Xz+y0/9NgmEcB1XR+yMtABSyBBHGuDG6xUWaJhc3unESgiceAqdoSv37+/x/URzHy9C8PBBYDog6E2AVYQbYCX/5cSoCvRGWV6TMmKIAPsqAJtIEH4AVhzT0vMbiet7fQsz3P9xAmLrgTTBsNYw+eRK9ejatHWCtAWtMDsalBmy5lTVeTbr702TZRUl83bSO9eFH/8mXDwtdZDasXHtyovH6tTctLrvLqVScsta/HNmHwkDUD8abejbqLwkKAduAmvOARmq7VTg9eML3h1D6Y9iwsvI5QrF+J/x0SEZcfG5sflSgt8kd5w4b61gUs94mL81m+Y2fjlh7ZG1T1xJGK8u9HjnxnPuzILijgLJB0qqpq/EkqM//EifmujpFczPxkcirxr1bVdX3iBlxZxtiWLbOBnVkWFcHbQJNc9DQ4/ynp+F+f98qaWdXA5Ootma+55kwPvZkchTQ5ka4QydJhuFCWnfp5hJbe79OjuW/Ar4CB4Aa4nWTvsiWBsIWdygL/P9vkDPwnb3PfWkZ2Sv/HCxwAXvcmnsXh20kOhql+g6qz6n+pOpalpSGuTEPLlXYoRadGKUAbBv5SgbG3U5hnnYkEXo8EhbcBqPD8qckMR40gHnW8LLSFKVre0Y2ChbIdgIXZCEhnR8HoSAWrs4dUjvkGGj19g5fOscCk6LahIDALzlOIjhKjqB8vWgwup8w8FIfkWmIabdcpaU0gkIjiscTFmMjofL6IOIkyxRTPGFMspbIoKy6HWIiOI3a7S3QrLisx0Egzpe7UqCi56kGRBpcDsDwKQocijER644ksDFycZK86hQufr0WYjGanozSUNGUlhMLD0rkoRqToDtQio7NTya2c4jGGSSyKkolkChcHUSHyE3aacRG5q/tZEQZUJPOAlFuqKKgkdzVGLm92vOEaaCO9MhjEIg5pQLj2iR5Co2PikrCsc5qMOqvFSzM5OgAAAA==') format('woff2'),url('./iconfont.woff?t=1551963575525') format('woff'),url('./iconfont.ttf?t=1551963575525') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */url('./iconfont.svg?t=1551963575525#iconfont') format('svg'); /* iOS 4.1- */
}.iconfont {font-family: "iconfont" !important;font-size: 16px;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}

7、图标字体可能是用于全局的,所以当成全局样式来处理,将iconfont.css文件改成iconfont.js,并修改为样式组件,内容如下:

import { createGlobalStyle } from 'styled-components';export const iconFontGlobal = createGlobalStyle `@font-face {font-family: "iconfont";src: url('./iconfont.eot?t=1551963575525'); /* IE9 */src: url('./iconfont.eot?t=1551963575525#iefix') format('embedded-opentype'), /* IE6-IE8 */url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPQAAsAAAAAB9gAAAOCAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqDFIJ7ATYCJAMQCwoABCAFhG0HRxvsBsgeh+kWI3+SnJzkPR6+v0/Pff9m3SxAmWAAMx7gZW3HK9aKFmtWXnaB/F9b+gfYhA51IebGpvWVYUUfO3VRUveT+E30FGkCBID6xL3Tpm2w+SzLaaxFa9P/3EVdgPHWwPbENmUFWiAJesvwapfCQR8mgLaBwqF1YXk98DhkVABxbzHpgM84cQ3kwEO8KhYmoCfQ4Mt85gGAx+D78Q+x8QCFpgIycXMsMEL2l//Xz+y0/9NgmEcB1XR+yMtABSyBBHGuDG6xUWaJhc3unESgiceAqdoSv37+/x/URzHy9C8PBBYDog6E2AVYQbYCX/5cSoCvRGWV6TMmKIAPsqAJtIEH4AVhzT0vMbiet7fQsz3P9xAmLrgTTBsNYw+eRK9ejatHWCtAWtMDsalBmy5lTVeTbr702TZRUl83bSO9eFH/8mXDwtdZDasXHtyovH6tTctLrvLqVScsta/HNmHwkDUD8abejbqLwkKAduAmvOARmq7VTg9eML3h1D6Y9iwsvI5QrF+J/x0SEZcfG5sflSgt8kd5w4b61gUs94mL81m+Y2fjlh7ZG1T1xJGK8u9HjnxnPuzILijgLJB0qqpq/EkqM//EifmujpFczPxkcirxr1bVdX3iBlxZxtiWLbOBnVkWFcHbQJNc9DQ4/ynp+F+f98qaWdXA5Ootma+55kwPvZkchTQ5ka4QydJhuFCWnfp5hJbe79OjuW/Ar4CB4Aa4nWTvsiWBsIWdygL/P9vkDPwnb3PfWkZ2Sv/HCxwAXvcmnsXh20kOhql+g6qz6n+pOpalpSGuTEPLlXYoRadGKUAbBv5SgbG3U5hnnYkEXo8EhbcBqPD8qckMR40gHnW8LLSFKVre0Y2ChbIdgIXZCEhnR8HoSAWrs4dUjvkGGj19g5fOscCk6LahIDALzlOIjhKjqB8vWgwup8w8FIfkWmIabdcpaU0gkIjiscTFmMjofL6IOIkyxRTPGFMspbIoKy6HWIiOI3a7S3QrLisx0Egzpe7UqCi56kGRBpcDsDwKQocijER644ksDFycZK86hQufr0WYjGanozSUNGUlhMLD0rkoRqToDtQio7NTya2c4jGGSSyKkolkChcHUSHyE3aacRG5q/tZEQZUJPOAlFuqKKgkdzVGLm92vOEaaCO9MhjEIg5pQLj2iR5Co2PikrCsc5qMOqvFSzM5OgAAAA==') format('woff2'),url('./iconfont.woff?t=1551963575525') format('woff'),url('./iconfont.ttf?t=1551963575525') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */url('./iconfont.svg?t=1551963575525#iconfont') format('svg'); /* iOS 4.1- */}.iconfont {font-family: "iconfont" !important;font-size: 16px;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
`;

8、在src/App.js里面引入该全局样式组件

import { iconfontGlobal } from './static/iconfont/iconfont.js';

9、将Header组件里面的搜索、Aa、笔用iconfont代替

{/* 使用iconfont,文字是图标的unicode,类名都是iconfont */}
<i className='iconfont'>&#xe636;</i>

 

搜索框动画效果实现(聚焦搜索框变宽,搜索按钮有背景色,blur则变小)

使用react-transition-group插件的CSSTransition组件,用css实现动画效果

 

使用react-redux进行应用数据管理------组件的数据使用react-redux管理的话,组件就变成无状态组件了,使得性能大大提升

在项目中安装redux(数据框架)

在项目中安装react-redux(方便我们在react中使用redux)

需要定义的文件有index.js(store),reducer.js,constantTypes.js,

 

使用combineReducers完成对数据的拆分管理

对react-redux中的数据在浏览器端调试的插件是redux-devtools-extend,要想在浏览器中使用该插件调试redux中的数据,需要在创建store的时候,进行配置

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

这篇关于生命周期函数、redux的使用(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/809530

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念