[react]展示组件和容器组件

本文译自Presentational and Container Components

我发现在写React应用时,有个设计模式非常有用。如果你有React的经验,估计你已经知道了——它就是容器组件这篇文章讲得很清楚了,但我想再补充几点。

有个办法能让组件更易懂、更容易复用,那就是将组件分成两类。我称之为容器组件展示组件,但也有人叫胖组件和瘦组件(Fat and Skinny)、智能组件和非智能组件(Smart and Dumb)、状态组件和纯组件(Stateful and Pure)、画面和组件(Screen and Component)等等。尽管它们并不完全相同,但基本的理念是一致的。

我所说的展示组件如下:

  • 关心组件的外观
  • 内部可能包含展示组件和容器组件,并且通常有自己的DOM标签和自己的样式。
  • 通常可以用this.props.children包含其他组件。
  • 不依赖于app的其他部分,如Flux action或store等。
  • 不需要指定如何加载或操作数据。
  • 通过props明确地接收数据、发起回调。
  • 绝大部分情况下自己没有状态(即使有,也通常是UI状态,而不是数据)
  • 可以写成函数型组件,除非需要状态、生命周期钩子函数,或者需要性能优化等
  • 例如:PageSidebarStoryUserInfoList

容器组件如下:

  • 关心组件如何工作
  • 可以包含展示组件和容器组件,但一般不会有自己的DOM标签(除了一些wrapping div之外),绝对不会有样式
  • 为展示组件或其他容器组件提供数据
  • 调用Flux action并将其作为回调函数提供给展示组件
  • 通常是有状态的(stateful),因为通常被作为数据源使用
  • 通常不是手写,而是由高阶组件生成,如React Redux的connect(),Relay的createContainer(),Flux Utils的Container.create()
  • 例如:UserPageFollowersSidebarStoryContainerFollowedUserList

为清晰期间,我会把它们放在不同的目录下。

(Read More)

[react]关于容器组件

本文译自Container Components

React的许多设计模式都给我的代码带来了深远的影响,而容器组件模式就是其中之一。

在React.js大会上,Jason Bonta介绍了他们在Facebook是如何构建高性能组件的,其中包含了这段关于容器组件的精髓.

其思想很简单:

容器负责获取数据,然后渲染到相应的子组件上。完毕。

“相应”的意思是同名的组件,例如:

StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList

明白了吧。

(Read More)

[ng1]路由和解决项的高级技巧

本文译自Advanced routing and resolves(原文副标题:避免AngularJS控制器中的回调陷阱)。

URL路由是Web应用中不可或缺的一部分。AngularJS自带的标准路由是ngRoute。在开发Angular应用的过程中你会首先熟悉ngRoute,并且它会陪伴你很久,但最终你会发现它无法满足你的需求。

默认的路由有许多限制,使得它并不太适合复杂的应用。实际上,它只能用在最小规模的项目上。显然AngularJS团队也注意到了这个问题,已把ngRoute移出了核心模块。从AngularJS 1.2开始,使用ngRoute就必须单独加载了。

本文简介:通过AngularUI Router和嵌套的解决项(resolve)将数据加载操作移出控制器(controller),避免控制器之间的耦合和代码重复。

(Read More)

[vagrant]解决vagrant up启动太慢的问题

在vagrant上使用Ubuntu时经常会出现启动过慢的问题。我的环境是MacBook Pro Mid 2015, OS X 10.11,vagrant上是Ubuntu 14.04, 使用一段时间后发现执行vagrant up时速度特别慢,查看控制台发现启动时经常出现这条消息:

cloud-init-nonet[14.57]: waiting 120 seconds for network device

搜了下发现原因是Ubuntu与Virtual Box带的Intel网卡驱动不兼容所致,改成AMD网卡驱动即可解决。 在Vagrantfile中添加以下配置即可解决(来源):

config.vm.provider "virtualbox" do |vb|
    ### Change network card to PCnet-FAST III
    # For NAT adapter
    vb.customize ["modifyvm", :id, "--nictype1", "Am79C973"]
    # For host-only adapter
    vb.customize ["modifyvm", :id, "--nictype2", "Am79C973"]
end

(Read More)

在Netgear R7000上定制dd-wrt

启用jffs

打开Web界面,进入Administration -> Management,找到”JFFS2 Support”节。默认状态下”Internal Flash Storage”应该是”Disable”的。

  1. 设置”Internal Flash Storage”为”Enable”,点击”Save”,再点击”Apply Settings”
  2. 设置”Clean Internal Flash Storage”为”Enable”,点击”Apply Settings”
  3. 此时应该能看到”Total / Free Size”处显示出了容量,例如”93.75MB / 91.33MB”
  4. 将”Clean Internal Flash Storage”改回”Disable”,点击”Save”再”Apply Settings”

启用USB

首先将USB盘插入R7000背面的USB2.0口中。我用的是一个256MB的小优盘。

打开Web界面,进入”Service” -> “USB”。然后进行以下设置:

  1. 设置”Core USB Support”为”Enable”,点击”Apply Settings”。
  2. 设置”USB Storage Support”为”Enable”,点击”Apply Settings”。
  3. 设置”Automatic Drive Mount”为”Enable”,点击”Apply Settings”。

此时通过ssh进入命令行,输入mount命令应该能看到优盘(通常为/dev/sda1)被mount到了/tmp/mnt/sda1。如果优盘不是ext2系统,可以通过fdiskmke2fs命令重新分区并格式化。

最后回到Web界面,将/dev/sda1的UUID(在Web界面上可以看到)填入”Mount this partition to /opt”中,以便路由器启动时能够自动挂载。

安装opkg

Kong的dd-wrt已经自带了opkg,只不过需要在启用USB之后安装一下。将USB挂载到/opt之后,运行

bootstrap

简单回答几个问题即可完成opkg的安装。

安装结束之后,打开/opt/etc/opkg.conf,填写以下内容:

src/gz base http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/base
src/gz kernel http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/kernel
src/gz luci http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/luci
src/gz management http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/management
src/gz packages http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/packages
src/gz routing http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/routing
src/gz targets http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/targets
src/gz telephony http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/telephony
dest root /opt
dest ram /tmp
lists_dir ext /opt/var/opkg-lists
option overlay_root /overlay
option check_signature 1

然后执行:

# opkg update
# opkg list

安装时opkg可能会报告找不到libc,只需要加上--force-depends强制安装即可。

# opkg install vim --force-depends

推荐的opkg packages

我只装了两个:

# opkg install vim
# opkg install htop

htop在执行时会报告terminal错误,可以通过以下命令解决:

export TERMINFO=/opt/usr/share/terminfo

我建了个/tmp/root/.profile文件如下:

alias vi='vim'
export TERMINFO=/opt/usr/share/terminfo

为避免重启路由器时内容丢失,可以将这个文件保存到/jffs/profile/.profile,然后通过Web界面添加一条启动命令(”Administration” -> “Commands” -> “Save Startup”):

# copy profile for shell
cp /jffs/profile/.* /tmp/root

(Read More)

Linksys E4200v2刷OpenWRT小记

几年前买过一台Linksys E4200。E4200有两个版本:rev1和rev2。熟悉dd-wrt的人可能知道, E4200v1使用的是Broadcom芯片,支持dd-wrt,但到了rev2就换成了Marvell芯片,不再支持dd-wrt,因此没法刷固件了。 很可惜,我购买时rev1已经断货,只好买了无法刷固件的rev2。

今天偶然查到,OpenWRT已经提供了E4200v2的支持,于是决定尝试一下。

刷机很容易,去设备页面上给出的链接下载openwrt-kirkwood-linksys-viper-squashfs-factory.bin, 然后连到路由器的固件升级页面升级即可。

刷机之后需要注意的几点(给熟悉dd-wrt的人):

  • OpenWRT的默认地址是192.168.1.1
  • OpenWRT默认不提供Web界面,首次登录只能通过SSH方式。用户名为root,无密码。请在登录之后使用passwd命令设置密码。
  • 连上Internet之后(我通过已有router使用DHCP连的,若需要PPPoE请参考OpenWRT官方文档),即可用以下命令安装web界面:

    opkg update
    opkg install luci               # 安装Web界面
    opkg install luci-ssl           # 安装SSL
    /etc/init.d/uhttpd start        # 启动Web界面
    /etc/init.d/uhttpd enable       # 设置Web界面自动启动
    
  • 该固件仅支持802.11n,不支持a/b/g。如果出现Wifi接口无法启动的故障,请自行编辑/etc/config/wireless,在相应的wifi-device节中添加option hwmode '11n'以强行设置网卡为802.11n。

(Read More)

A script that changes MAC address

Here is a script that can change your MAC address automatically. Just save it as ~/bin/macchange and add ~/bin to your path. Tested on Mac OSX Yosemite.

Type macchnage to change MAC address to a random one. Type macchange restore to restore MAC address to origin.

if [[ $1 == 'restore' ]]
then
  action='restored'
  mac=$(cat ~/bin/mac.origin)
else
  action='changed'
  mac=$(openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//')
fi

sudo ifconfig en0 ether $mac

echo $action MAC to $mac

ifconfig en0

(Read More)

[python]cx_Oracle安装笔记

要安装cx_Oracle包,需要首先下载Oracle的客户端库文件和头文件。访问OTN,下载相应操作系统的Instant Client Basic Package和SDK Package。64位Linux对应的文件名分别为instantclient-basic-linux.x64-12.1.0.2.0.zipinstantclient-sdk-linux.x64-12.1.0.2.0.zip

(Read More)

[js]奇怪的Grunt问题

不知何时起我的构建CSS Sprite的grunt task突然不能运行了。CSS Sprite是利用grunt-spritesmith构建的。原本以为是配置文件的问题,于是反复删改Gruntfile.js中的sprite段配置,无果;又以为是引擎的问题,于是反复安装、删除各种图形处理模块,也无果。最后偶然读到grunt-spritesmith的源代码,发现它注册了一个名叫sprite的任务。突然想起我自己好像也注册了同名任务:

grunt.registerNpmTask('sprite', ['sprite']);

原来如此!我本想用我注册的sprite任务去调用grunt-spritesmithsprite任务,结果两个正好同名,导致死循环调用。。。解决方法,把这行删掉就可以了。

记录下来引以为戒。

(Read More)

[Oracle]How to Unlock Expired Account

If you ever get this error in your dev then you should consider unlock your oracle account and set it to never expire.

ORA-28001: the password has expired

Login with your system account and run the following SQLs.

-- find out your profile name
SELECT profile FROM DBA_USERS WHERE username='<username>';

-- check password limit
SELECT resource_time, limit FROM DBA_PROFILES WHERE profile='<profile_name>';

-- reset password and unlock account
ALTER USER <username> IDENTIFIED BY <new_password> ACCOUNT UNLOCK;

-- disable expiration
ALTER PROFILE <profile_name> LIMIT password_life_time UNLIMITED;

-- disable password policy
ALTER PROFILE <profile_name> LIMIT password_verify_function NULL;

Then your account should be ready to use.

(Read More)