课程名称: React零基础入门到实战,完成企业级项目简书网站开发
课程章节: 项目实战:Header组件开发
主讲老师: Dell
今天学习的内容包括:
基于react的组件化思想,用styled-components对样式也进行了组件化,这样每个组件拥有了自己的功能,还拥有了自己的样式,从而能够实现真正意义上的复用。react通过state来控制组件,而styled-components也可以通过state的改变来动态的改变组件的样式。
reset.css: 不同浏览器等内核里,对浏览器等标签默认样式是不同的,为了让我们的代码在所有浏览器上表现形式是一致的,先把浏览器对一些标签的默认形式进行统一,reset.css就是解决这个问题的。
styled-components ,v4 已经删除了 injectGlobalStyle 全局方法, 对应解决方法是 需要把
1.用createGlobalStyle定义全局样式
import { createGlobalStyle } from 'styled-components' export const Globalstyle = createGlobalStyle` body{ margin: 0; padding: 0 }
然后按照样式组件引入即可
2. 在项目主文件导入样式
import { Globalstyle } from './style'
3.以样式组件的方式当作标签引入
render() { return ( <div> <Globalstyle/> </div> );
styled-Component不会干扰其他样式的原因是因为,它将css抽离成一个组件,只用使用的时候才会引入。
它可以直接给标签添加属性,通过attrs({arrtsName: value}),也可以直接在组件上写属性。attrs上的属性优先级是大于组件上书写的属性。
// 跳转到"/123",而不是"/" "export const Logo = styled.a.attrs({href: '/123'})" "<Logo href="/">"
style-components实例:
搜索框重要内容:
export const NavSearch = styled.input.attrs({ placeholder: '搜索' })` box-sizing:border-box;//保证总长度为设定的width outline:none;//焦点在时搜索框外没有被选中的黑线 border-radius:19px;//设置搜索框的圆角 background:#eee; font-size:14px; &::placeholder {//搜索框内的文字效果 &::;若要选中某个类,则用&.xxx{} color:#969696 }
import { createGlobalStyle } from 'styled-components';export const GlobalFontStyle = createGlobalStyle` @font-face { font-family: 'iconfont'; /* Project id 2468859 */ src: url('//at.alicdn.com/t/font_2468859_bis8y7il1.woff2?t=1634457194883') format('woff2'), url('//at.alicdn.com/t/font_2468859_bis8y7il1.woff?t=1634457194883') format('woff'), url('//at.alicdn.com/t/font_2468859_bis8y7il1.ttf?t=1634457194883') format('truetype'); } .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } `;
<Fragment>
中即可。import React, { Fragment } from 'react';import ReactDOM from 'react-dom';import App from './App';import { GlobalStyle } from './style';import { GlobalFontStyle } from './statics/iconfont/iconfont'ReactDOM.render( <Fragment> <GlobalStyle/> <GlobalFontStyle/> <App/> </Fragment>, document.getElementById('root'))
<SearchWrapper> <NavSearch></NavSearch> <span className="iconfont"></span></SearchWrapper>
yarn add react-transition-group 安装动画插件
import { CSSTransition } from ‘react-transition-group’; 引入
<CSSTransition>把需要动画的元素包裹起来</CSSTransition>
再配置一下三个状态样式
.slide-enter{} //入场 .slide-enter-active{} //选中 .slide-exit{} //出厂 .slide-exit-active{} //出厂之后
子组件使用父组件中provider中传过来的数据的方法
//接收的store的数据 const mapStateToProps = (state) =>{ return{ } }
//要修改数据时调用的dipatch方法写到里面,也就是指store.dispatch()方法
const mapDispathToProps = (dispatch) =>{ return{ } } export default connect(mapStateToprops,mapDispathToprops)(Header)
import { combineReducers } from 'redux'; import {reducer as headerReducer} from '../pages/header/store' const reducer = combineReducers({ header: headerReducer }) // 将不同页面的reducer统一合并 export default reducer
随着项目建设,如果将所有变量和逻辑都写在reducer中,会导致reducer文件变得臃肿且逻辑复杂。所以需要对reducer进行拆分。
使用"combineReducers"函数,对多个reducer进行整个,然后引出。
store/reducer.js const reducer = combineReducer({header: componentReducer}) export default reducer
header 组件里面设置统一出口是败笔,要做太多的工作了。
在header组件内直接调用store里面的文件就好
在统一的reducer里面引用一下header的reduce
import * as actionCreators from './store/actionCreators'; 要用到es6的语法,我用老师带中括号的方法提示Unexpected token错误。去掉“{}”就不报错了。
1、immutable库提供一个fromJS方法,可以把一个JS对象转换为immutable(不可变)对象;
2、使用immutable.js之后,不能用“.”访问store中的对象,要使用get()方法;
3、使用immutable.js之后,修改store中的数据时,要使用set方法;
4、immutable对象的set方法,会结合之前immutable对象的值和设置的值,返回一个全新的对象,并没有改变原始的state;
immutable.js
1.npm i immutable --save
2.header/store/reducer.js import { fromJS} from immutable
3.const initialState = fromJs({focused: false})
React只能兼容到IE8
getListArea(参数: props.focused)
Redux store 仅支持同步数据流。使用 thunk 等中间件可以帮助在 Redux 应用中实现异步性。可以将 thunk 看做 store 的 dispatch() 方法的封装器;我们可以使用 thunk action creator 派遣函数或 Promise,而不是返回 action 对象。
注意,没有 thunk 的话,默认地是同步派遣。也就是说,我们依然可以从 React 组件发出 API 调用(例如使用 componentDidMount() 生命周期方法发出这些请求),但是我们在 Redux 应用中难以实现以下两点:
可重用性(思考下合成)
可预测性,只有 action creator 可以是状态更新的单一数据源
getListArea方法,在一个普通的组件里, 没必要传‘’show’'参数了. 直接用this.props.focused
想从store取数据, 在mapStateToProps 里面去写: stage.getIn(['header]. ‘list’)
dispatch对应的方法里对应的data就是immutable的类型了, reducer接收到的action的data也会是immutable的类型了, 实现了数据统一.
map方法对数据进行循环展示每一项
传递action前,把 action里的data也转换成immutable 数组
dispatch方法, 异步axios请求数据, 如果成功了, 执行then( () => {} )方法;
如果失败了, 执行 catch方法
1、异步获取的逻辑拆分到actionCreactors, action中要求返回一个函数,用到react-thunk中间件
2、获取store数据想要改变注意,reducer外层包裹一个fromJS把内部数据类型改变成immutable数据,数据类型要统
一,把actionCreactors传递之前把action中的数据转换成immutable数据类型{impot {fromJS} from ‘immutable’;}
3、调用map()循环展示
结构赋值, const { focused, list } = this.props
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
根据list的size属性来判断需不需要请求数据