课程章节: 项目实战:Header组件开发
主讲老师: Dell
课程内容:
今天学习的内容包括:
基于react的组件化思想,用styled-components对样式也进行了组件化,这样每个组件拥有了自己的功能,还拥有了自己的样式,从而能够实现真正意义上的复用。react通过state来控制组件,而styled-components也可以通过state的改变来动态的改变组件的样式。
reset.css: 不同浏览器等内核里,对浏览器等标签默认样式是不同的,为了让我们的代码在所有浏览器上表现形式是一致的,先把浏览器对一些标签的默认形式进行统一,reset.css就是解决这个问题的。
课程收获:
7.1 心得:
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>
);
7.2 心得:
styled-Component不会干扰其他样式的原因是因为,它将css抽离成一个组件,只用使用的时候才会引入。
它可以直接给标签添加属性,通过attrs({arrtsName: value}),也可以直接在组件上写属性。attrs上的属性优先级是大于组件上书写的属性。
// 跳转到"/123",而不是"/"
"export const Logo = styled.a.attrs({href: '/123'})"
"<Logo href="/">"
7.3 心得:
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
}
7.4 心得:
- 首先./statics/iconfont/iconfont.js中只需要把之前本地链接改成在线链接即可,@font-face这块可以直接在官网复制。还有一点是现在应该使用createGlobalStyle方法来定义全局样式。
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;
}
`;
- 然后在index.js中引用一下,写在
<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>
7.5 心得:
yarn add react-transition-group 安装动画插件
import { CSSTransition } from ‘react-transition-group’; 引入
<CSSTransition>把需要动画的元素包裹起来</CSSTransition>
再配置一下三个状态样式
.slide-enter{} //入场
.slide-enter-active{} //选中
.slide-exit{} //出厂
.slide-exit-active{} //出厂之后
7.6 心得:
子组件使用父组件中provider中传过来的数据的方法
//接收的store的数据
const mapStateToProps = (state) =>{
return{
}
}
//要修改数据时调用的dipatch方法写到里面,也就是指store.dispatch()方法
const mapDispathToProps = (dispatch) =>{
return{
}
}
export default connect(mapStateToprops,mapDispathToprops)(Header)
7.7 心得:
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
7.8 心得:
header 组件里面设置统一出口是败笔,要做太多的工作了。
在header组件内直接调用store里面的文件就好
在统一的reducer里面引用一下header的reduce
import * as actionCreators from './store/actionCreators';
要用到es6的语法,我用老师带中括号的方法提示Unexpected token错误。去掉“{}”就不报错了。
7.9 心得:
1、immutable库提供一个fromJS方法,可以把一个JS对象转换为immutable(不可变)对象;
2、使用immutable.js之后,不能用“.”访问store中的对象,要使用get()方法;
3、使用immutable.js之后,修改store中的数据时,要使用set方法;
4、immutable对象的set方法,会结合之前immutable对象的值和设置的值,返回一个全新的对象,并没有改变原始的state;
7.10 心得:
immutable.js
1.npm i immutable --save
2.header/store/reducer.js import { fromJS} from immutable
3.const initialState = fromJs({focused: false})
7.11 心得:
React只能兼容到IE8
getListArea(参数: props.focused)
Redux store 仅支持同步数据流。使用 thunk 等中间件可以帮助在 Redux 应用中实现异步性。可以将 thunk 看做 store 的 dispatch() 方法的封装器;我们可以使用 thunk action creator 派遣函数或 Promise,而不是返回 action 对象。
注意,没有 thunk 的话,默认地是同步派遣。也就是说,我们依然可以从 React 组件发出 API 调用(例如使用 componentDidMount() 生命周期方法发出这些请求),但是我们在 Redux 应用中难以实现以下两点:
可重用性(思考下合成)
可预测性,只有 action creator 可以是状态更新的单一数据源
7.12 心得:
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()循环展示
7.13 心得:
结构赋值, const { focused, list } = this.props
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
7.14 心得:
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
7.15 心得:
mapToStateProps, 把totalPage也拿进来, 获取总页码,
如果当前页码小于totalPage, 就下页, 否则就改回第一页,.
ac里可以接收到Page这个新页码, 把新页码传递给reducer.
reducer里changePage被接收到的时候, 同时action里, 也会有page的这个属性.——是即将要替换的这个页码.
7.16 心得:
根据list的size属性来判断需不需要请求数据