Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
Flux
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
Flux概述
Flux是Facebook用来构建用户端的web应用的应用程序体系架构。它通过利用数据的单向流动为React的可复用的视图组件提供了补充。相比于形式化的框架它更像是一个架构思想,不需要太多新的代码你就可以马上使用Flux构建你的应用。
Flux应用主要包括三部分:dispatcher、store和views(React components),千万不要和MVC(model-View-Controller)搞混。Controller在Flux应用中也确实存在,但是是以controller-view的形式。view通常处于应用的顶层,它从stores中获取数据,同时将这些数据传递给它的后代节点。另外,action creators - dispatcher辅助方法 - 一个被用来提供描述应用所有可能存在的改变的语义化的API。把它理解为Flux更新闭环的第四个组成部分可以帮助你更好的理解它。
Flux使用单向的数据流动来避开MVC. 当用户与React视图交互的时候,视图会通过中枢dispatcher产生一个action。然后大量的保存着应用数据和业务逻辑的视图接收到冒泡的action,更新所有受影响的view。这种方式很适合React这种声明式的编程方式,因为它的store更新,并不需要特别指定如何在view和state中过渡。
我们独创性的解决了数据的获取:举个栗子,比如我们需要展示一个会话列表,高亮其中未读的会话,同时展示未读会话的数量。如果用MVC架构的话将很难处理这种情况,因为更新一个对话为已读的时候会更新对话model,然后同样也需要更新未读对话数量model(数量-1)。这样的依赖和瀑布式的更新在大型的应用中非常常见,导致错综复杂的数据流动和不可预测的结果。(这其实是Facebook之前的一个线上bug,有时候用户看到提示说有一条未读信息,但是点进去却发现没有)。
反过来让 Store 来控制:store接受更新,并在合适的时机处理这些更新。而不是采用一贯依赖外部的方式来更新数据。在store外部,并没办法看到store内部是如何处理它内部的数据的,这样的方式保证了一个清晰的关注点分离。Store并没有类似setAsRead()这样直接的setter方法,但是在其自成一体的世界中拥有唯一个获取新数据的方法 - store通过dispatcher注册的回调函数。
Structure and Data Flow
Flux中数据是单项流动的:
用户的交互可能会使views产生新的action。
A Single Dispatcher
dispatcher 就像是一个中央的集线器,管理着所有的数据流。本质上它就是 store callback 的注册表,本身并没有实际的高度功能。它就是一个用来向stores分发actions的机器。 每一个 store 各自注册自己的 callback 以提供对应的处理动作。当 dispatcher 发出一个 action 时,应用中所有的store都会通过注册的callback收到这个action。
Stores
Stores 包含了应用的状态和逻辑。
store在dispatcher中注册,并提供相应的回调。
store更新完成之后,会向应用中广播一个change事件,views可以选择响应事件来重新获取新的数据并更新。
Views and Controller-Views
React提供了一种可组合式的view让我们可以自由组合展示层。在接近顶层的地方,有些view需要监听所依赖的store的广播事件。我们称之为controller-view,因为他们提供了胶水代码来从store中获取数据,并向下层层传递这些数据。我们会利用这些controller-views来处理页面上某些重要部分。
Actions
dispatcher提供了一个可以允许我们向store中触发分发的方法,我们称之为action。
What About that Dispatcher?
dispatcher也可以用来管理store之间的依赖。
Flux TodoMVC Tutorial
ReactJS插件
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
插件
React.addons
是为了构建 React 应用而放置的一些有用工具的地方。此功能应当被视为实验性的,但最终将会被添加进核心代码中或者有用的工具库中:
TransitionGroup
和CSSTransitionGroup
,用于处理动画和过渡,这些通常实现起来都不简单,例如在一个组件移除之前执行一段动画。LinkedStateMixin
,用于简化用户表单输入数据和组件 state 之间的双向数据绑定。classSet
,用于更加干净简洁地操作 DOM 中的 class 字符串。cloneWithProps
,用于实现 React 组件浅复制,同时改变它们的 props 。update
,一个辅助方法,使得在 JavaScript 中处理不可变数据更加容易。PureRenderMixin
,在某些场景下的性能检测器。
以下插件只存在于 React 开发版(未压缩):
TestUtils
, 简单的辅助工具,用于编写测试用例(仅存在于未压缩版).Perf
,用于性能测评,并帮助你检查出可优化的功能点。
要使用这些插件,需要用react-with-addons.js
(和它的最小化副本)替换常规的React.js。
当通过npm使用react包的时候,只要简单地用require('react/addons')
替换 require(‘react’) 来得到带有所有插件的React。
ReactJS 参考
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
1、顶层API
1.1、React
React 是 React 库的入口。如果使用的是预编译包,则 React 是全局的;如果使用 CommonJS 模块系统,则可以用 require() 函数引入 React。
React.createClass
创建一个组件类,并作出定义。组件实现了 render() 方法,该方法返回一个子级。该子级可能包含很深的子级结构。
React.createElement
创建并返回一个新的指定类型的 ReactElement。
React.createFactory
返回一个生成指定类型 ReactElements 的函数。
React.render
渲染一个 ReactElement 到 DOM 中。
React.unmountComponentAtNode
从 DOM 中移除已经挂载的 React 组件,清除相应的事件处理器和 state。
React.renderToString
把组件渲染成原始的 HTML 字符串。该方法应该仅在服务器端使用。
React.renderToStaticMarkup
和 renderToString 类似,除了不创建额外的 DOM 属性,例如 data-react-id,因为这些属性仅在 React 内部使用。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为丢掉额外的属性能够节省很多字节。
React.isValidElement
判断对象是否是一个 ReactElement。
React.DOM
React.DOM 运用 React.createElement 为 DOM 组件提供了方便的包装。该方式仅在未使用 JSX 的时候适用。例如,React.DOM.div(null, ‘Hello World!’)。
React.PropTypes
React.PropTypes 包含了能与组件 propTypes 对象共用的类型,用于验证传入组件的 props。
React.initializeTouchEvents
配置 React 的事件系统,使 React 能处理移动设备的触摸( touch )事件。
React.Children
React.Children 为处理 this.props.children 这个封闭的数据结构提供了有用的工具。
React.Children.map
在每一个直接子级(包含在 children 参数中的)上调用 fn 函数,此函数中的 this 指向 上下文。如果 children 是一个内嵌的对象或者数组,它将被遍历:不会传入容器对象到 fn 中。
React.Children.forEach
类似于 React.Children.map(),但是不返回对象。
React.Children.count
返回 children 当中的组件总数,和传递给 map 或者 forEach 的回调函数的调用次数一致。
React.Children.only
返回 children 中仅有的子级。否则抛出异常。
2、组件API
ReactComponent。唯一一种在 React 之外获取 React 组件实例句柄的方式就是保存 React.render 的返回值。在其它组件内,可以使用 refs 得到相同的结果。
2.1、setState
合并 nextState 和当前 state。这是在事件处理函数中和请求回调函数中触发 UI 更新的主要方法。
绝对不要直接改变 this.state;
setState() 不会立刻改变 this.state,而是创建一个即将处理的 state 转变;
不保证 setState() 调用的同步性;
setState() 将总是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。
2.2、replaceState
类似于 setState(),但是删除之前所有已存在的 state 键,这些键都不在 nextState 中。
2.3、forceUpdate()
如果 render() 方法从 this.props 或者 this.state 之外的地方读取数据,你需要通过调用 forceUpdate() 告诉 React 什么时候需要再次运行 render()。如果直接改变了 this.state,也需要调用 forceUpdate()。
通常情况下,应该尽量避免所有使用forceUpdate()的情况。
2.4、getDOMNode
如果组件已经挂载到了 DOM 上,该方法返回相应的本地浏览器 DOM 元素。
2.5、iSMounted()
如果组件渲染到了 DOM 中,isMounted() 返回 true。
2.6、setProps()
可以调用 setProps() 来改变组件的属性,触发一次重新渲染。
刚方法仅在根组件上面调用。也就是说,仅在直接传给 React.render() 的组件上可用,在它的子级组件上不可用。如果你倾向于在子组件上使用 setProps(),不要利用响应式更新,而是当子组件在 render() 中创建的时候传入新的 prop 到子组件中。
2.7、replaceProps
类似于 setProps(),但是删除所有已存在的 props,而不是合并新旧两个 props 对象。
3、组件的详细说明和生命周期
3.1、组件的详细说明
render
当调用的时候,会检测 this.props 和 this.state,返回一个单子级组件。
render() 函数应该是纯粹的,也就是说该函数不修改组件 state,每次调用都返回相同的结果,不读写 DOM 信息,也不和浏览器交互(例如通过使用 setTimeout)。
getInitialState
在组件挂载之前调用一次。返回值将会作为 this.state 的初始值。
getDefaultProps
在组件类创建的时候调用一次,然后返回值被缓存下来。如果父组件没有指定 props 中的某个键,则此处返回的对象中的相应属性将会合并到 this.props (使用 in 检测属性)。
propTypes
propTypes 对象允许验证传入到组件的 props。
mixins
mixin 数组允许使用混合来在多个组件之间共享行为。
statics
statics 对象允许你定义静态的方法,这些静态的方法可以在组件类上调用。
displayName
displayName 字符串用于输出调试信息。
3.2、组件的生命周期
挂载:componentWillMount
服务器端和客户端都只调用一次,在初始化渲染执行之前立刻调用。如果在这个方法内调用 setState,render() 将会感知到更新后的 state,将会执行仅一次,尽管 state 改变了。
挂载:componentDidMount
在初始化渲染执行之后立刻调用一次,仅客户端有效(服务器端不会调用)。在生命周期中的这个时间点,组件拥有一个 DOM 展现,你可以通过 this.getDOMNode() 来获取相应 DOM 节点。
如果想和其它 JavaScript 框架集成,使用 setTimeout 或者 setInterval 来设置定时器,或者发送 AJAX 请求,可以在该方法中执行这些操作。
更新:componentWillReceiveProps
在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。
用此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。老的 props 可以通过 this.props 获取到。在该函数中调用 this.setState() 将不会引起第二次渲染。
更新:shouldComponentUpdate
在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会。
如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。
更新:componentWillUpdate
在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用。
使用该方法做一些更新之前的准备工作。
你不能在刚方法中使用 this.setState()。如果需要更新 state 来响应某个 prop 的改变,请使用 componentWillReceiveProps。
更新:componentDidUpdate
在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。
使用该方法可以在组件更新之后操作 DOM 元素。
移除:componentWillUnmount
在组件从 DOM 中移除的时候立刻被调用。
在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount 中创建的 DOM 元素。
3、标签和属性支持
3.1、支持的标签
React 尝试支持所用常用的元素。如果你需要的元素没有在下面列出来,请提交一个问题(issue)。
HTML元素
SVG元素
3.2、支持度 属性
React 支持所有 data- 和 aria- 属性,也支持下面列出的属性。
所有的属性都是驼峰命名的,class 属性和 for 属性分别改为 className 和 htmlFor,来符合 DOM API 规范。
HTML属性
1 | accept acceptCharset accessKey action allowFullScreen allowTransparency alt |
SVG属性
1 | cx cy d dx dy fill fillOpacity fontFamily fontSize fx fy gradientTransform |
4、事件系统
4.1、虚拟事件对象
事件处理器将会传入虚拟事件对象的实例,一个对浏览器本地事件的跨浏览器封装。它有和浏览器本地事件相同的属性和方法,包括 stopPropagation() 和 preventDefault(),但是没有浏览器兼容问题。
如果因为一些因素,需要底层的浏览器事件对象,只要使用nativeEvent
属性就可以获取到它了。每一个虚拟事件对象都有下列的属性:
1 | boolean bubbles |
4.2、支持的事件
React 标准化了事件对象,因此在不同的浏览器中都会有相同的属性。
如下的事件处理器在事件冒泡阶段触发。要在捕获阶段触发某个事件处理器,在事件名字后面追加 Capture
字符串;例如,使用 onClickCapture
剪贴板事件
onCopy onCut onPaste
键盘事件
onKeyDown onKeyPress onKeyUp
焦点事件
onFocus onBlur
表单事件
onChange onInput onSubmit
鼠标事件
onClick onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave
onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
触摸事件
onTouchCancel onTouchEnd onTouchMove onTouchStart
UI事件
onScroll
鼠标滚轮滚动事件
onWheel
5、与DOM的差异
React 为了性能和跨浏览器的原因,实现了一个独立于浏览器的事件和 DOM 系统。利用此功能,可以屏蔽掉一些浏览器的 DOM 的粗糙实现。
6、特殊的非DOM属性
除了与 DOM 的差异之外,React 也提供了一些 DOM 里面不存在的属性:
- key
- ref
- dangerouslySetInnerHTML
7、Reconciliation
这篇文章解释了我们如何使用强大的试探法来将 O(n3) 复杂度的问题转换成 O(n) 复杂度的问题。
7.1、动机
生成最少的将一颗树形结构转换成另一颗树形结构的操作,是一个复杂的,并且值得研究的问题。最优算法的复杂度是 O(n3),n 是树中节点的总数。
7.2、两个节点的差异检查
不同的节点类型
如果节点的类型不同,React 将会把它们当做两个不同的子树,移除之前的那棵子树,然后创建并插入第二棵子树。
DOM节点
当比较两个 DOM 节点的时候,我们查看两者的属性,然后能够找出哪一个属性随着时间产生了变化。
自定义组件
因为组件是状态化的,不可能每次状态改变都要创建一个新的组件实例。React 利用新组件上的所有属性,然后在之前的组件实例上调用 component[Will/Did]ReceiveProps()。
7.2、子级优化差异算法(List-wise diff)
问题点(Problematic Case)
为了完成子级更新,React 选用了一种很原始的方法。React 同时遍历两个子级列表,当发现差异的时候,就产生一次 DOM 修改。
键(Keys)
为了解决这个看起来很棘手的问题,引入了一个可选的属性。可以给每个子级一个键值,用于将来的匹配比较。如果指定了一个键值,React 就能够检测出节点插入、移除和替换,并且借助哈希表使节点移动复杂度为 O(n)。
7.3、权衡(Trade-offs)
为了完成子级更新,React 选用了一种很原始的方法。React 同时遍历两个子级列表,当发现差异的时候,就产生一次 DOM 修改。
8、React(虚拟)DOM术语
五个核心类型:
1 | ReactElement / ReactElement 工厂 |
8.1、React元素
React 中最主要的类型就是 ReactElement。它有四个属性:type,props,key 和 ref。它没有方法,并且原型上什么都没有。
可以通过 React.createElement 创建该类型的一个实例。
1 | var root = React.createElement('div'); |
要添加属性到 DOM 元素,把属性对象作为第二个参数传入 React.render,把子级作为第三个参数传给 React.render。
1 | var child = React.createElement('li', null, 'Text Content'); |
如果使用 React JSX 语法,这些 ReactElement 实例自动创建。
工厂
一个 ReactElement 工厂就是一个简单的函数,该函数生成一个带有特殊 type 属性的 ReactElement:
1 | function createFactory(type){ |
该函数能创建一个方便的短函数,而不是总调用 React.createElement(‘div’):
1 | var div = React.createFactory('div'); |
React 已经内置了常用 HTML 标签的工厂函数:
1 | var root = React.DOM.ul({ className: 'my-list' }, |
如果使用 JSX 语法,就不需要工厂函数了。JSX 已经提供了一种方便的短函数来创建 ReactElement 实例。
8.2、React节点
一个 ReactNode 可以是:
- ReactElement
- string (又名 ReactText)
- number (又名 ReactText)
- ReactNode 实例数组 (又名 ReactFragment)
8.3、React组件
在使用 React 开发中,可以仅使用 ReactElement 实例,但是,要充分利用 React,就要使用 ReactComponent 来封装状态化的组件。
一个 ReactComponent 类就是一个简单的 JavaScript 类(或者说是“构造函数”)。
1 | var MyComponent = React.createClass({ |
当该构造函数调用的时候,应该会返回一个对象,该对象至少带有一个 render 方法。该对象指向一个 ReactComponent 实例。
除非为了测试,正常情况下不要自己调用该构造函数。React 帮你调用这个函数。
把 ReactComponent 类传给 createElement,就会得到一个 ReactElement 实例。
1 | var element = React.createElement(MyComponent); |
或者使用 JSX:
1 | var element = <MyComponent />; |
当该实例传给 React.render 的时候,React 将会调用构造函数,然后创建并返回一个 ReactComponent。
1 | var component = React.render(element, document.body); |
如果一直用相同的 ReactElement 类型和相同的 DOM 元素容器调用 React.render,将会总是返回相同的实例。该实例是状态化的。如果自己手动创建Componnet实力,则不会又这样的优化。
ReactComponent 的 render 方法应该返回另一个 ReactElement,这就允许组件被组装。
8.4、正式的类型定义
入口点
节点和元素
类和组件
ReactJS入门
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
1、数据呈现
响应式更新(Reactive Updates)
this.props
是只读的。
组件就像是函数
React组件非常像函数,接收props
和status
作为参数,然后渲染出HTML。
JSX语法
ReactJS中相信:标签与生成它的代码是紧密相连的,所以不做模板引擎
和展示逻辑
的分离。最好的方法是通过Javascript直接生成模板,为此JSX派上用场了:一个非常简单、可选类似 HTML 语法 ,通过函数调用即可生成模板的编译器。
JSX 让你可以用 HTML 语法去写 JavaScript 函数调用。
1 React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello React!')。
JSX语法:1
<a href="http://facebook.github.io/react/">Hello React!</a>
1.1、深入理解JSX
JSX是一个看起来像XML的JavaScript语法扩展。React可以用来做简单的JSX句法转换。
1.1.1、为什么要使用JSX
能够定义简洁且我们熟知的包含属性的树状结构语法。
1.1.2、HTML标签与React组件对比
React 的 JSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。
1.1.3、转换
1 | // JSX |
1 | var Nav, Profile; |
1.1.4、JavaScript表达式
属性表达式
使用JavaScript表达式作为属性值,使用{}1
2
3
4
5
6
7// JSX
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// 等价于
var person = React.createElement(
Person,
{name: window.isLoggedIn ? window.name : ''}
);
子节点表达式
1 | // JSX |
注释
JSX 里添加注释很容易;它们只是 JS 表达式而已。你只需要在一个标签的子节点内(非最外层)小心地用 {} 包围要注释的部分。
1 | var content = ( |
1.2、JSX的延展属性
Props 应该被当作禁止修改的。修改 props 对象可能会导致预料之外的结果,所以最好不要去修改 props 对象。
延展属性(Spread Attributes)
这个...
操作符(也被叫做延展操作符 - spread operator)已经被 ES6 数组 支持。
1 | var props = { foo: 'default' }; |
1.3、JSX的陷阱
HTML实体
如果想在 JSX 表达式中显示 HTML 实体,可以会遇到二次转义的问题,因为 React 默认会转义所有字符串,为了防止各种 XSS 攻击。
1 | // 错误: 会显示 “First · Second” |
解决方法:
- 直接使用Unicode字符串
1 | <div>{'First · Second'}</div> |
- 使用Unicode编号
1 | <div>{'First \u00b7 Second'}</div> |
- 在数组里面使用字符串和JSX元素
1 | <div>{['First ', <span>·</span>, ' Second']}</div> |
- 使用原始HTML
1 | <div dangerouslySetInnerHTML={{__html: 'First · Second'}} /> |
自定义HTML属性
React里面如果需要使用自定义属性,要加 data- 前缀。
1 | <div data-custom-attribute="foo" /> |
2、富交互性的动态用户界面
2.1、事件处理与合成事件(Synthetic Events)
1 | React.initializeTouchEvents(true); 启用触摸事件处理。 |
2.2、幕后原理:自动绑定和事件代理
在幕后,React 做了一些操作来让代码高效运行且易于理解。
Autobinding
: 在 JavaScript 里创建回调的时候,为了保证 this 的正确性,一般都需要显式地绑定方法到它的实例上。有了 React,所有方法被自动绑定到了它的组件实例上。
事件代理
: React 实际并没有把事件处理器绑定到节点本身。
2.3、组件其实是状态机(State Machines)
React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。
2.4、State 工作原理
常用的通知 React 数据变化的方法是调用 setState(data, callback)。这个方法会合并(merge) data 到 this.state,并重新渲染组件。渲染完成后,调用可选的 callback 回调。
2.5、哪些组件应该有 State?
有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
2.6、哪些 应该 作为 State?
State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。
2.7、哪些 不应该 作为 State?
this.state 应该仅包括能表示用户界面状态所需的最少数据。因此,它不应该包括:
- 计算所得数据
- React组件
- 基于props的重复数据
3、复合组件
3.1、动机:关注分离
通过复用那些接口定义良好的组件来开发新的模块化组件,我们得到了与使用函数和类相似的好处。
3.2、组合实例
1 | var Avatar = React.createClass({ |
3.3、从属关系
组件不能修改自身的 props - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的关键性原则。
3.4、子级
实例化 React 组件时,你可以在开始标签和结束标签之间引用在React 组件或者Javascript 表达式:
1 | <Parent><Child /></Parent> |
Parent
能通过专门的this.props.children props
读取子级。this.props.children
是一个不透明的数据结构: 通过React.Children
工具类 来操作。
3.5、子级校正(Reconciliation)
校正就是每次 render 方法调用后 React 更新 DOM 的过程。
1 | // 第一次渲染 |
React 是根据子级的顺序来校正的。
3.6、子组件状态管理
对于使用 this.state 来在多次渲染过程中里维持数据的状态化组件,上面例子这样做潜在很多问题。
多数情况下,可以通过隐藏组件而不是删除它们来绕过这些问题。
3.7、动态子级
如果子组件位置会改变(如在搜索结果中)或者有新组件添加到列表开头(如在流中)情况会变得更加复杂。
果子级要在多个渲染阶段保持自己的特征和状态,在这种情况下,你可以通过给子级设置惟一标识的 key 来区分。
1 | render: function() { |
务必 把 key 添加到子级数组里组件本身上,而不是每个子级内部最外层 HTML 上。
也可以传递 object 来做有 key 的子级。
1 | render: function() { |
3.8、数据流
数据通过上面介绍过的 props 从拥有者流向归属者。这就是高效的单向数据绑定(one-way data binding)
3.9、性能提醒
能的瓶颈大多是因为 DOM 更新,而非 JS 执行,而且 React 会通过批量更新和变化检测来优化性能。
有时候需要做细粒度的性能控制。这种情况下,可以重写 shouldComponentUpdate() 方法返回 false 来让 React 跳过对子树的处理。
不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。
自己实现一个单向数据绑定?
4、可复用组件
把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。
4.1、Prop 验证
React.PropTypes 提供很多验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 propTypes。
4.2、默认 Prop 值
1 | var ComponentWithDefaultProps = React.createClass({ |
当父级没有传入 props 时,getDefaultProps() 可以保证 this.props.value 有默认值,注意 getDefaultProps 的结果会被 缓存。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。
4.3、传递 Props:小技巧
JSX 的 spread 语法
1 | var CheckLink = React.createClass({ |
4.4、单个子级
React.PropTypes.element 可以限定只能有一个子级传入。
1 | var MyComponent = React.createClass({ |
4.5、Mixins
有时一些复杂的组件间也需要共用一些功能。有时会被称为跨切面关注点
。React 使用mixins
来解决这类问题
1 | var SetIntervalMixin = { |
5、传递Props
可以使用 JSX 展开属性 来合并现有的 props 和其它值:
1 | return <Component {...this.props} more="values" />; |
也可以使用一些对象辅助方法如 ES6 的 Object.assign 或 Underscore _.extend。
1 | return Component(Object.assign({}, this.props, { more: 'values' })); |
5.1、手动传递
大部分情况下你应该显式地向下传递 props。这样可以确保只公开你认为是安全的内部 API 的子集。
1 | var FancyCheckbox = React.createClass({ |
5.2、在 JSX 里使用 … 传递
有时把所有属性都传下去是不安全或啰嗦的。这时可以使用解构赋值
中的剩余属性特性来把未知属性批量提取出来。
列出所有要当前使用的属性,后面跟着...other
。
1 | var { checked, ...other } = this.props; |
这样能确保把所有 props 传下去,除了 那些已经被使用了的。
1 | var FancyCheckbox = React.createClass({ |
在传递这些未知的other
属性时,要经常使用解构赋值模式。
5.3、使用和传递同一个 Prop
如果组件需要使用一个属性又要往下传递,可以直接使用checked={checked}
再传一次。这样做比传整个this.props
对象要好,因为更利于重构和语法检查。
1 | var FancyCheckbox = React.createClass({ |
5.4、剩余属性和展开属性 …
剩余属性可以把对象剩下的属性提取到一个新的对象。会把所有在解构赋值中列出的属性剔除。
这是 ES7 草案 中的试验特性。
1 | var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; |
使用 JSX 命令行工具 配合 –harmony 标记来启用 ES7 语法。
5.5、使用 Underscore 来传递
在不适用JSX的情况下,可以使用一些库来实现相同的效果,如Undersocre
。
6、表单组件
表单事件:onChange onInput onSubmit
6.1、交互属性
表单组件支持几个受用户交互影响的属性:
- value,用于 、
- checked,用于类型为 checkbox 或者 radio 的 组件。
- selected,用于
6.2、受限组件
设置了 value 的 是一个受限组件。相当于设置了只读属性。
如果想响应更新用户输入的值,就得使用 onChange 事件:
1 | getInitialState: function() { |
6.3、不受限组件
没有设置 value(或者设为 null) 的 组件是一个不受限组件。
如果想给组件设置一个非空的初始值,可以使用 defaultValue 属性。
6.4、高级主题
为什么使用受限组件?
在 HTML 中将渲染初始值为 Untitled 的输入框。用户改变输入框的值时,节点的 value 属性(property)将随之变化,但是 node.getAttribute(‘value’) 还是会返回初始设置的值 Untitled.
与 HTML 不同,React 组件必须在任何时间点描绘视图的状态
,而不仅仅是在初始化时。比如在 React 中:
1 | render: function() { |
该方法在任何时间点渲染组件以后,输入框的值就应该始终为 Untitled。
为什么
React 是 JavaScript,没有字符限制,可以使用 \n 实现换行。简言之,React 已经有 value、defaultValue 属性, 组件的子
如果非要*使用子节点,效果和使用 defaultValue 一样。
为什么
React 为了更方面的控制组件。
给 value 属性传递一个数组,可以选中多个选项:
7、浏览器中的工作原理
React提供了强大的抽象,让你在大多数应用场景中不再直接操作DOM,但是有时你需要简单地调用底层的API,或者借助于第三方库或已有的代码。
7.1、虚拟DOM
React是很快的,因为它从不直接操作DOM。React在内存中维护一个快速响应的DOM描述。render()方法返回一个DOM的描述,React能够利用内存中的描述来快速地计算出差异,然后更新浏览器中的DOM。
有时你简单地需要调用底层的API,或许借助于第三方的类似于jQuery插件这种库。React为你提供了直接使用底层DOM API的途径。
7.2、Refs和getDOMNode()
每一个挂载的React组件有一个getDOMNode()方法,你可以调用这个方法来获取对该节点的引用。
getDOMNode()仅在挂载的组件上有效。在创建组件的render()函数中调用getDOMNode(),将会抛出异常。
为了获取一个到React组件的引用,你可以使用this来得到当前的React组件,或者你可以使用refs来指向一个你拥有的组件。
7.3、组件生命周期
- 挂载: 组件被插入到DOM中。
- 更新: 组件被重新渲染,查明DOM是否应该刷新。
- 移除: 组件从DOM中移除。
挂载
getInitialState()
object在组件被挂载之前调用。状态化的组件应该实现这个方法,返回初始的state数据。componentWillMount()
在挂载发生之前立即被调用。componentDidMount()
在挂载结束之后马上被调用。需要DOM节点的初始化操作应该放在这里。
更新
componentWillReceiveProps(object nextProps)
当一个挂载的组件接收到新的props的时候被调用。该方法应该用于比较this.props和nextProps,然后使用this.setState()来改变state。shouldComponentUpdate(object nextProps, object nextState)
boolean当组件做出是否要更新DOM的决定的时候被调用。实现该函数,优化this.props和nextProps,以及this.state和nextState的比较,如果不需要React更新DOM,则返回false。componentWillUpdate(object nextProps, object nextState)
在更新发生之前被调用。你可以在这里调用this.setState()。componentDidUpdate(object prevProps, object prevState)
在更新发生之后调用。
移除
componentWillUnmount()
在组件移除和销毁之前被调用。清理工作应该放在这里。
挂载的方法(Mounted Methods)
挂载的复合组件也支持如下方法:
getDOMNode()
: DOMElement可以在任何挂载的组件上面调用,用于获取一个指向它的渲染DOM节点的引用。forceUpdate()
: 当你知道一些很深的组件state已经改变了的时候,可以在该组件上面调用,而不是使用this.setState()。
7.4、跨浏览器支持和兼容代码
在Facebook,我们支持低版本的浏览器,包括IE8。
8、关于Refs的更多内容
input 元素一些东西 - 这些东西过会儿(onClick,onChange事件后)之后已无法从它的 props 中推算出来。在这个场景中,我们想“通知” input 元素,现在应该处于获取焦点状态。然而,此处有一些障碍。从 render() 中返回的内容并不是你实际创建的子组件的组合,仅仅是一个某一刻某个组件实例的 描述 - 一个快照。
记住,从 render() 中返回的内容并不是实际渲染出来的子组件实例。从 render() 返回的仅仅是子组件层级树实例在特定时间的一个描述。
1 | // counterexample: DO NOT DO THIS! |
在这个反例中, 仅仅是一个 组件的描述。该描述用于创建一个真正的 的支撑实例
( backing instance )。为了获取真正的Input的支撑实力,我们需要使用到ref属性
8.1、ref 属性
React 支持一种非常特殊的属性,你可以用来绑定到 render() 输出的任何组件上去。这个特殊的属性允许你引用 render() 返回的相应的支撑实例
( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。
- 1、绑定一个 ref 属性到 render 返回的东西上面去
1 | <input ref="myInput" /> |
- 2、在其它代码中(典型地事件处理代码),通过 this.refs 获取支撑实例
1 | this.refs.myInput |
9、工具集成
9.1、React
9.2、JSX
VIM常用命令
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
复制粘贴
vi编辑器中的整行(多行)复制与粘贴就非常必要了。
1、复制
1)单行复制
在命令模式下,将光标移动到将要复制的行处,按yy
进行复制;2)多行复制
在命令模式下,将光标移动到将要复制的首行处,按nyy
复制n行;其中n为1、2、3……按y复制选中区域
2、粘贴
在命令模式下,将光标移动到将要粘贴的行处,按p
进行粘贴。
其他方式
命令模式:
命令行模式下输入
6,9 co 12
复制第6行到第9行之间的内容到第12行后面。
使用标签法:
光标移到起始行,输入
ma
光标移到结束行,输入mb
光标移到粘贴行,输入mc
然后 :'a,'b co 'c
把 co 改成 m 就成剪切了
要删除多行的话,可以用 :5, 9 de
选择
v:按字符选择。经常使用的模式,所以亲自尝试一下它。
V:按行选择。这在你想拷贝或者移动很多行的文本的时候特别有用。
CTRL+v:按块选择。
其他命令
u 撤销
ctrl + r 重做
PropertyPlaceholderConfigurer的应用
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
PropertyPlaceholderConfigurer的应用
安装Jar包本地仓库
Git常用命令
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
Git常用命令
1 | # 将远程分支信息获取到本地 |
分支管理
设置推送分支
1 | git remote add origin https://github.com/... |
查看分支
1 | git branch |
创建分支
1 | # 创建test分支 |
切换分支
1 | # 切换到test分支 |
删除分支
undefinedRebase 相关命令
1 | git rebase origin |
Tag管理
删除远程Tag
undefined从版本库中删除文件:
git rm -r –cached
References
IntelliJ IDEA插件安装
IntellJ IDEA Mac常用快捷键
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
导航
⌘O 查找类文件 Ctrl + N
⌘⌥O 前往指定的变量 / 方法 Ctrl + Shift + Alt + N
⌃← / ⌃→ 左右切换打开的编辑tab页 Alt← / Alt→
⎋ 从工具窗口进入代码文件窗口 ESC
⌘L 在当前文件跳转到某一行的指定处 Ctrl + G
⌘E 显示最近打开的文件记录列表 Ctrl + E
⌘⌥← / ⌘⌥→ 退回 / 前进到上一个操作的地方 Ctrl + Alt + ← Ctrl + Alt + →
⌘⇧⌫ 跳转到最后一个编辑的地方
⌃H 显示当前类的层次结构 Ctrl + H
⌘⇧H 显示方法层次结构
⌃⌥H 显示调用层次结构
F4 / ⌘↓ 编辑/查看代码源
⌘⌥U 显示类UML图
⌃J 查看注释
编辑
⌥⌦ 删除到单词的末尾(⌦键为Fn+Delete)
⌥⌫ 删除到单词的开头
⌘+ / ⌘- 展开 / 折叠代码块
⌘F1 在错误或警告处显示具体描述信息
⌘⌥L 格式化代码
⌃⌥O 优化import
⇧↩ 开始新的一行
⌘⇧↩ 自动结束代码,行末自动添加分号
⌃I 实现方法(实现接口中的方法)
⇧F6 重命名文件或者变量
⌘N, ⌃↩, ⌃N 生成代码(getter、setter、构造函数、hashCode/equals,toString)
⌘P 显示方法的参数信息
查找
Double⇧ 查找任何东西
⌘⇧F 全局查找(根据路径)
⌘F 文件内查找
⌘G 查找模式下,向下查找
⌘⇧G 查找模式下,向上查找
导航
⌘⌥B 跳转到接口的实现
⌘U 查看接口定义
⌘⌥← / ⌘⌥→ 退回 / 前进到上一个操作的地方
⌘B / ⌘ 鼠标点击 进入光标所在的方法/变量的接口或是定义处
⌃⇧B 跳转到类型声明处
⌥ Space, ⌘Y 快速打开光标所在方法、类的定义
⌘O 查找类文件
⌘⇧O 查找所有类型文件、打开文件、打开目录,打开目录需要在输入的内容前面或后面加一个反斜杠/
F12 返回到前一个工具窗口
⎋ 从工具窗口进入代码文件窗口
⇧⎋ 隐藏当前或最后一个活动的窗口,且光标进入代码文件窗口
F3选中文件/文件夹/代码行,添加/取消书签
⌥F3 选中文件/文件夹/代码行,使用助记符添加/取消书签
⌃0…⌃9 定位到对应数值的书签位置
⌘F3 显示所有书签
⌥F1 显示当前文件选择目标弹出层,弹出层中有很多目标可以进行选择(如在代码编辑窗口可以选择显示该文件的Finder)
⌘F12 弹出当前文件结构层,可以在弹出的层上直接输入进行筛选(可用于搜索类中的方法)
通用
⌃⌘F 切换全屏模式
产品销售市场的各个阶段
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in:
从产品销售市场分析自己的职业发展
一个产品从被发明,到打开市场,到需求旺盛,知道一个新的技术革新取代旧的产品,每一个阶段都有不同的营销策略,用对了营销策略,则可以在市场中占据有利的位置。
每一个阶段的需要不同的销售人员类型,不同的销售人员类型同样的可以类比到其他职业中。
就程序员来说
如果你是一个缔结者,那么适合创建一些革新的产品,始终走在技术前沿,成为技术的布道者,用技术让世界更加美好,对应的是底层框架,基础设施的编写者,或者是新技术的创造者;
如果你是一个建设者,那么适合在一个团队中循序渐进的成长,在必业务场景必须进行引入一些新技术的时候,把一个比较成熟的新技术推给一个团队,从而推动团队技术的发展,以让业务得以继续正常的发展;
References
《卖轮子-选择最佳营销方式》
Git配置
Mac实用快捷键
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
Mac下相关快捷键
Mac 菜单和键盘通常使用某些按键的符号,其中包括以下修饰键:1
2
3
4
5
6Command ⌘
Shift ⇧
Option ⌥
Control ⌃
Caps Lock ⇪
Fn
输入法
快速切换中英文:caps lock
,按了之后caps lock
键会亮起绿灯。
编辑
截图
- command+shift+3是全屏截图
- command+shift+4是局部截图
图片默认存储在桌面。
设置截图保存路径
打开Terminal
并输入如下命令:1
defaults write com.apple.screencapture location /path/
/path/即你想要设置的保存路径,比如将截图文件存储在用户目录的图片(Pictures)文件夹,命令则为:1
defaults write com.apple.screencapture location ~/Pictures/
接下来,为了使得修改生效,输入下面这条命令:1
killall SystemUIServer
当然,如果你习惯将截图保存在桌面的话,/path/ 对应的路径为 ~/Desktop/。
设置截图文件格式
OS X 系统默认截图文件格式为 png,通过下面的终端(Terminal)命令可以修改截图文件格式为 jpg :1
defaults write com.apple.screencapture type jpg
另外,还可以将命令中的 jpg 修改为 gif 或 pdf,以及改回默认的 png 格式。同样别忘了输入上面那条使得修改生效的命令。
⌘ t: 新建一个tab页
⌘ shift []: 切换tab页
IntelliJ IDEA系列1
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
修改主题
IntelliJ IDEA对目录做了调整,把偏好设置调整到了如下目录:
IntelliJ IDEA –> preferences(快捷键:⌘,) –> Appearance & Behavior –> Appearance –> UI Options –> Theme
旧版本的可以在file --> Settings中找到
。
编译
有如下三种编译:
- Compile
对特定的代码文件进行强制编译;
- Rebuild
对选择的project进行强制编译;
- Make
对选定的Project或者Module进行编译,只编译改动过的文件;
shift + command + F9
compile one class.
Run配置
Run –> Edit Configurations
项目结构设置
file –> project structrue(快捷键:⌘;)
可以在这里管理SDK版本(Platform Settings –> SDKs),设置项目SDK(Project Settings –> Project)。
language level
对于大型项目,各个 Module 用到的 SDK 和 language level 很有可能是各不一样的,IntelliJ IDEA 对此也进行了支持。(Project Settings –> Modules –> Sources –> Lauguage Level…)
编辑
实时代码模板
1 | IntelliJ IDEA --> Editor --> Live Template |
提示快捷键:Tab
和 Ctrl + J
文件代码模板
1 | Prefrences --> Editor --> File and code Template |
IntelliJ IDEA 的文件代码模板是可以用Velocity Template Language进行书写的;
Emmet的使用
该工具常用于前端代码的自动生成;
Postfix Completion的使用
代码模板的自动补全功能
1 | Preferences --> Editor --> General --> Postfix Completion |
插件讲解
官方插件库1
Preferences --> Plugins
Eclipse的Java Web项目环境搭建
Maven项目介绍
Debug讲解
重构讲解
数据库管理工具
IntelliJ IDEA常用设置
IntelliJ IDEA常用快捷键讲解(Win + Linux)
IntelliJ IDEA常用快捷键讲解(Mac)
IntelliJ IDEA的Java热部署插件JRebel安装及使用
References
Mac实用工具
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
Mac实用工具安装
安装程序
安装maven
1 | sudo tar -zxvf 压缩文件名.tar.gz -C /usr/local/maven |
安装MySQL
安装Tomcat
安装Nginx
安装Memcached
安装 MySQL客户端
安装office
SecureCRT
Mac下面的SecureCRT(附破解方案) 更新到最新的7.2的破解方案
brew
安装命令如下:
1 | curl -LsSf http://github.com/mxcl/homebrew/tarball/master | sudo tar xvz -C/usr/local --strip 1 |
当brew安装成功后,就可以随意安装自己想要的软件了,例如wget,命令如下:
1 | sudo brew install wget |
卸载的话,命令如下:
1 | sudo brew uninstall wget |
查看安装软件的话,命令如下:
1 | sudo brew search /apache*/ |
注意/apache*/是使用的正则表达式,用/分割。
nginx
1、brew search nginx
2、brew install nginx
启动nginx ,sudo nginx ;访问localhost:8080 发现已出现nginx的欢迎页面了。
备注: ln -s /usr/local/sbin/nginx /usr/bin/nginx 做个软连接。
常用的指令有:
nginx -V 查看版本,以及配置文件地址
nginx -v 查看版本
nginx -c filename 指定配置文件
nginx -h 帮助
重新加载配置|重启|停止|退出 nginx
nginx -s reload|reopen|stop|quit
打开 nginx
sudo nginx
测试配置是否有语法错误
nginx -t
配置shell
配置zsh:http://www.cnblogs.com/GarveyCalvin/p/4301235.html
Vimium
其他实用工具
使用NodeJS模块
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
淘宝npm镜像
npm
https://docs.npmjs.com/cli/install
https://docs.npmjs.com/misc/config
Autoprefixer
Babel
Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。
如果你想要在命令行使用Babel,你可以安装babel-cli
,或者你需要在一个Node项目中使用Babel,你可以使用babel-core
。
插件预设
官方的预设包括babel-preset-es2015
和babel-preset-react
Lodash
extract-text-webpack-plugin
ionic视频
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in:
视频地址:
1 | http://pan.baidu.com/s/1c0obKIk#path=%252Fphonegap%25E7%25AC%25AC%25E4%25B8%2589%25E5%25AD%25A3%2520angularjs%252Bionic%25E8%25A7%2586%25E9%25A2%2591%25E6%2595%2599%25E7%25A8%258B%2520%25E5%25AE%259E%25E6%2597%25B6%25E5%258F%2591%25E5%25B8%2583%252Fphonegap%25E7%25AC%25AC%25E4%25B8%2589%25E5%25AD%25A3%2520angularjs%252Bionic%25E8%25A7%2586%25E9%25A2%2591%25E6%2595%2599%25E7%25A8%258B%25E3%2580%2590Avi%25E6%25A0%25BC%25E5%25BC%258F%25E3%2580%2591 |
AngularJS之filter
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
1、HTML模板中的过滤器:1
{{ name | uppercase }}
使用:传递参数给过滤器:
1
2 <!-- 显示:123.46 -->
{{ 123.456789 | number:2 }}可以用|符号作为分割符来同时使用多个过滤器。
2、在JavaScript代码中可以通过$filter
来调用过滤器:1
2
3
4app.controller('DemoController', ['$scope', '$filter',
function($scope, $filter) {
$scope.name = $filter('lowercase')('Ari');
}]);
3、AngularJS提供的内置过滤器:
1. currency1
{{ 123 | currency }}
2. date1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49{{ today | date:'medium' }} <!-- Aug 09, 2013 12:09:02 PM -->
{{ today | date:'short' }} <!-- 8/9/1312:09PM -->
{{ today | date:'fullDate' }} <!-- Thursday, August 09, 2013 -->
{{ today | date:'longDate' }} <!-- August 09, 2013 -->
{{ today | date:'mediumDate' }}<!-- Aug 09, 2013 -->
{{ today | date:'shortDate' }} <!-- 8/9/13 -->
{{ today | date:'mediumTime' }}<!-- 12:09:02 PM -->
{{ today | date:'shortTime' }} <!-- 12:09 PM -->
年份格式化
四位年份:{{ today | date:'yyyy' }} <!-- 2013 -->
两位年份:{{ today | date:'yy' }} <!-- 13 -->
一位年份:{{ today | date:'y' }} <!-- 2013 -->
月份格式化
英文月份:{{ today | date:'MMMM' }} <!-- August -->
英文月份简写:{{ today | date:'MMM' }} <!-- Aug -->
数字月份:{{ today |date:'MM' }} <!-- 08 -->
一年中的第几个月份:{{ today |date:'M' }} <!-- 8 -->
日期格式化
数字日期:{{ today|date:'dd' }} <!-- 09 -->
一个月中的第几天:{{ today | date:'d' }} <!-- 9 -->
英文星期:{{ today | date:'EEEE' }} <!-- Thursday -->
英文星期简写:{{ today | date:'EEE' }} <!-- Thu -->
小时格式化
24小时制数字小时:{{today|date:'HH'}} <!--00-->
一天中的第几个小时:{{today|date:'H'}} <!--0-->
12小时制数字小时:{{today|date:'hh'}} <!--12-->
上午或下午的第几个小时:{{today|date:'h'}} <!--12-->
分钟格式化
数字分钟数:{{ today | date:'mm' }} <!-- 09 -->
一个小时中的第几分钟:{{ today | date:'m' }} <!-- 9 -->
秒数格式化
数字秒数:{{ today | date:'ss' }} <!-- 02 -->
一分钟内的第几秒:{{ today | date:'s' }} <!-- 2 -->
毫秒数:{{ today | date:'.sss' }} <!-- .995 -->
字符格式化
上下午标识:{{ today | date:'a' }} <!-- AM -->
四位时区标识:{{ today | date:'Z' }} <!--- 0700 -->
下面是一些自定义日期格式的示例:
{{ today | date:'MMMd, y' }} <!-- Aug9, 2013 -->
{{ today | date:'EEEE, d, M' }} <!-- Thursday, 9, 8-->
{{ today | date:'hh:mm:ss.sss' }} <!-- 12:09:02.995 -->
3. filter
这个过滤器的第一个参数可以是字符串、对象或是一个用来从数组中选择元素的函数。
4. json
son过滤器可以将一个JSON或JavaScript对象转换成字符串。
5. limitTo
limitTo过滤器会根据传入的参数生成一个新的数组或字符串,新的数组或字符串的长度取决于传入的参数,通过传入参数的正负值来控制从前面还是从后面开始截取。
6. lowercase
7. number
number过滤器将数字格式化成文本。它的第二个参数是可选的,用来控制小数点后截取的位数。
8. orderBy
orderBy可以接受两个参数,第一个是必需的,第二个是可选的。
第一个参数是用来确定数组排序方向的谓词。第二个参数用来控制排序的方向(是否逆向)。1
orderBy:'name':true
9. uppercase
uppercase过滤器可以将字符串转换为大写形式。
7.1、自定义过滤器
创建一个过滤器:
1 | angular.module('myApp.filters', []) |
使用:
1 | <!-- Ginger loves dog treats --> |
7.2、表单验证
AngularJS提供了很多表单验证指令。
input元素上使用的所有验证选项:
必填项
1
<input type="text" required />
最小长度
1
<input type="text" ng-minlength="5" />
最大长度
1
<input type="text" ng-maxlength="20" />
模式匹配
1
<input type="text" ng-pattern="[a-zA-Z]" />
电子邮件
1
<input type="email" name="email" ng-model="user.email" />
数字
1
<input type="number" name="age" ng-model="user.age" />
URL
1
<input type="url" name="homepage" ng-model="user.facebook_url" />
自定义验证
需要使用到指令的相关内容,第10章再深入研究如何创建自定义验证。在表单中控制变量
一些有用的CSS样式
$parsers:
使用$parsers数组是实现自定义验证的途径之一。
$formatters:
- 组合实例
AngularJS之scope
Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com
- 作用域是视图和控制器之间的胶水。
- 作用域是应用状态的基础。
- AngularJS将$scope设计成和DOM类似的结构,因此$scope可以进行嵌套,也就是说我们可以引用父级$scope中的属性。
- 作用域提供了监视数据模型变化的能力。它允许开发者使用其中的apply机制,将数据模型的变化在整个应用范围内进行通知。
将应用的业务逻辑都放在控制器中,而将相关的数据都放在控制器的作用域中,这是非常完美的架构。
4.1、视图和$scope的世界
ng-app元素同$rootScope进行绑定,$rootScope是所有$scope对象的最上次。
4.2、就是HTML而已
在AngularJS应用的模板中使用多种标记,包括下面这些:
指令:将DOM元素增强为可复用的DOM组件的属性或元素。
值绑定:模板语法{{ }}可以将表达式绑定到视图上。
过滤器:可以在视图中使用的函数,用来进行格式化。
表单控件:用来检验用户输入的控件。
4.3、作用于能做什么
作用域有以下的基本功能:
提供观察者以监视数据模型的变化;
可以将数据模型的变化通知给整个应用,甚至是系统外的组件;
可以进行嵌套,隔离业务功能和数据;
给表达式提供运算时所需的执行环境。
4.4、$scope的生命周期
$scope对象的生命周期处理有四个不同阶段:
4.4.1、创建
在创建控制器或指令时,AngularJS会用$injector
创建一个新的作用域,并在这个新建的控制器或指令运行时将作用域传递进去。
4.4.2、链接
当Angular开始运行时,所有的$scope对象都会附加或者链接到视图中。这些作用域将会注册当Angular应用上下文中发生变化时需要运行的函数。($watch函数
)
4.4.3、更新
通常事件循环运行在$rootScope,每个子域都会进行脏值检查,如果检测到变化,$scope对象就会触发指定的回调函数。
4.4.4、销毁
当一个$scope在视图中不再需要时,这个作用域将会清理和销毁自己。
4.5、指令和作用域
指令在AngularJS中被广泛使用,指令通常不会创建自己的$scope,但也有例外。比如ng-controller
和ng-repeat
指令会创建自己的子作用域并将它们附加到DOM元素上。