组件化设计思路

  |  
 阅读次数

组件化的设计思路

组件封装有一定的不确定性,更多时候在几方面做个权衡,在最开始并不可能做到完美,在业务的不断变化中,可能还会面临一些调整和重构

组件化的意义
1 组件化是实现分层。更有效的代码组合方式
2 组件化是对资源的重组和优化,从而是项目管理更加合理
3 有利于单元测试
4 对重构友好

组件的定义
1 可复用的模块,完成既定的功能
2 有明确的接口规定
3 有上下文依赖 外部依赖资源定义
4 可以独立发布

组件设计的原则 主要的是复用性
1 使用单一职责原则
2 适用开放封闭原则
3 追求短小精悍
4 避免太多参数
5 缩小信赖范围和想稳定方向的信赖
6 追求无副作用
7 追求透明化
8 入口处检查参数的有效性,出口处检查返回的正确性
9 充分隔离变化的部分

自省的几个问题
组件是否有必要再分
组件划分的依据通常是业务逻辑、功能、要考虑组件之间的关系是否明确
划分粒度的大小需要根据实际情况权衡,大小会提升维护成本,太大又不够灵活和高复用性
每一个组件都应该有起独特的划分目的,有的是为了复用实现,有的是为了封装的复杂度清晰业务实现

2 组件的依赖是否可以再缩减
3 组件的可复用于其他类似场景中
在考虑需要适用的不同场景,在组件接口设计时需要兼容
4 组件当别人使用时,会怎么想
5 假如业务需要不需要这个功能,是否清楚方便

敲代码的李二狗:

为什么说 Java 程序员必须掌握 Spring Boot ?

SVN使用指南

  |  
 阅读次数

几个概念要必须掌握:

checkout—>将SVN仓库的代码烤到本地,比如你现在参与一个团队项目,项目代码在你之前肯定已经写了很多了,你可以通过checkout项目代码,获得整个项目。

update—>在你写代码的过程中,同事很可能已经提交过代码到SVN服务器,而你本地项目显然没有同事新提交的代码,你可以通过update SVN获得SVN最新的代码。

commit—>当你完成一部分开发后,你可以通过commit提交代码到SVN服务器,这样别人就可以获得你写的代码,记得 先update再commit

TortoiseSVN图标介绍

  • 绿色对勾重载,表示Svn状态正常
  • 红色感叹号,表示文件状态状态变成 已修改
  • 黄色感叹号,表示提交过程出现冲突
  • 蓝色加号,表示 一个 文件/目录 已经被加入到 版本控制中

SVN Client 基础操作

  1. SVN检出(Checkout)\
    输入 url , 确定本地 代码库 地址

弹出用户名 密码验证

Add 增加

  1. 先提交到变更列表,再 commit 到配置库:选择新增文件,右键SVN菜单执行Add, 提交到变更列表,然后右键SVN菜单执行SVN Commit提交到版本库

  2. 不提交到变更列表,直接commit配置库:直接选择文件,右键SVN菜单执行SVN Commit操作。

Delete 删除

如果被删文件 未入版本库,可直接使用操作系统删除

如果被删文件 已入版本库:

  1. 选择被删文件, 右键 SVN菜单 执行delete操作
  2. 选择被删文件父级目录, 右键 SVN菜单 执行SVN Commit

Rename 改名

SVN Revert 还原

右键SVN菜单 Update to reversion

React学习笔记

  |  
 阅读次数

第一步 实现功能模块

  1. npm install antd –save-dev
  2. import ‘antd css style sheets’
  3. 创建 模板
  4. import {Menu, Table, Pagination} from ‘antd’;
  5. 导出模板到 ./index.js
  6. Router 注册; Nav 里面 添加 路由 link
    Compelite

四大部分(props state lifecircle context)

组件构建三种方法

① React.createClass

1
2
3
const Button = React.createClass({
// method/lifecircle
})

② ES6class

③ 无状态函数
无状态组件只传入propscontext,不存在state.
propsTypsdefaultProps 可通过 向 方法 设置 静态属性

组件五种形式

[容器, 业务逻辑, 取数据, 布局(layout), 无状态组件]

生命周期(lifecircle)

参考文档
初始化:

1
2
3
4
constructor
componentWillMount
+ render()
componentDidMount

周期改变:(props/state 改变时 触发)

1
2
3
4
5
6
7
8
9
10
componentWillReceiveProps(nextProps) {
<!-- 当组件可能接收到`新道具`时调用。即使道具没有改变,你也可以这样称呼它,所以如果你只想处理改变,一定要比较新的和现有的道具。 -->
<!-- 调用组件setstate通常不会触发这种方法。 -->
}
shouldComponentUpdate(nextProps, nextState)
componentWillUpdata() {
<!-- willUpdata 下 设置 setState 会触发 componentReceiveProps -->
}
+ render()
componentDidUpdata

组件销毁:

1
componentDis

单向数据流

被动接收 => 数据流逻辑

无状态组件如何避免重绘(reflow)/重排版(repaint)

避免组件reRender

在 React 中,组件 state 的变化会触发该组件以下的整个组件子树的重新渲染。为了避免不必要的子组件重新渲染, 我们需要使用 PureComponent,或尽量实现 shouldComponentUpdate。还需要使用不可变的数据结构让 state 的变化更容易被优化:

与其他框架的比较——Vue.js

React-Router

reactRouter的三种形式

  • hashHistory
  • browserHistory
  • createMemoryHistory

React 路由跳转

1
this.props.history.push('/login')

React路由 与 浏览器历史回退

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** 
* 初始化 获取 window.location.href
*/
constructor(props, context) {
super(props, context)
this.curUrl = window.location.href.split('/')
this.state = {
current: this.curUrl[6] || this.curUrl[5],
}
this.handleClick = this.handleClick.bind(this);
}

/** 页面、路由变动时,再次 获取当前路由 */
componentWillReceiveProps() {
this.curUrl = window.location.href.split('/')

this.setState({
current: this.curUrl[6] || this.curUrl[5],
})
}

React.Children.map渲染对象

1
2
3
4
5
{
React.Children.map(children, (child) => {
return <Fragment>{child}</Fragment>
})
}

React-router 去掉url上的

1
2
3
4
import {browserHistory} from 'react-router'
<Router history={browserHistory}>
...
</Router>

React-Context应用

父组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** 先定义 类似 ts中 interface  */
export const Context = React.createContext({
updateHomeState: () => { },
homeState: {}
});

render() {
// debugger
return (
<Context.Provider value={{
updateHomeState: this.updateHomeState,
homeState: this.state
}}>
<div className="main">
<div className="center">
{/* 中间地图 */}
<CenterMap />
</div>
</div>
</Context.Provider>
);
}

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { Context } from "src/views/Home/Home"; // 先引入

render() {
return (
/* 引用 祖先组件的 context */
<Context.Consumer>
{
({ updateHomeState, homeState }) => (
<div className="CenterMap">
<MapTopMenu
tableListSize={homeState.tableListSize}
updateHomeState={updateHomeState}
onChange={this.onChange}
/>
</div>
)
}
</Context.Consumer>
);
}

React获取真实DOM元素[ref], 并获取元素样式

1
2
3
4
5
6
<div
className='navContainer'
ref={navContainer => this.navContainer = navContainer} // ref 支持接收函数进行赋值
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
1
2
3
4
5
6
7
8
9
// 获取样式
const cssStyle = navContainer.currentStyle
? navContainer.currentStyle
: document.defaultView.getComputedStyle(navContainer, null)

// 获取详细样式
const pr = navContainer.currentStyle
? parseInt(cssStyle.paddingRight, 10)
: parseInt(cssStyle['padding-right'], 10)

Redux学习笔记

  |  
 阅读次数

dispatch

1
2
3
4
5
6
7
8
function (action) {
if (sagaMonitor && sagaMonitor.actionDispatched) {
sagaMonitor.actionDispatched(action);
}
var result = next(action); // hit reducers
sagaEmitter.emit(action);
return result;
};

项目中学习Redux

记录在脚手架学习Demo中尝试使用Redux的过程。

  1. 定义
  2. Action中创建AppRedux文件夹, 创建action.AppRedux.type.js \
    内容如下:

    export const APP_REDUX = “APP_REDUX”;

  3. Action文件夹下index中引入 需要抛出的变量

    import {APP_REDUX} from ‘./AppRedux/action.appRedux.type’;

  4. 定义 一个 Reducer APP_REDUX, 并引入 action 变量 type
  5. 每次程序 dispatch 一个 action,所有 reducer 都会在当前reducer中通过 switch 语句 判断 action 是否 触发本状态
    7.
    1
    2
    3
    import { combineReducers } from 'redux';

    // 所有 reducer 通过 `combineReducers({...Reducers})`方法