mobile first
virtual-dom
React.Component
&& React.createClass
&& stateless
Component
learn once, write anywhere
(React-Native)React.renderToString
React.renderToString
React.PropTypes
130kb
): 始祖37kb
): 基于 refer 与 virtual-dom 库(请勿用于生产环境)13kb
): ES2015 实现, 无依赖(请勿用于生产环境)just virtual-dom and component
React.createElement
: 创建 virtual-domReact.createClass
: 创建 ComponentReact.Component
: 支持 ES2015 classesReact.render
: 渲染 virtual-dom 到 real-domlet createElement = (type, props, ...children) => {
return {
type,
props,
children
}
}
var link = React.createElement('a', {
href: 'https://www.strikingly.com/'
}, 's','t','r','i','k','i','n','g','l','y')
var link = <a href="https://www.strikingly.com/">strikingly</a>
var create = function(vnode) {
switch (true) {
case isStr(vnode) || isNum(vnode):
return document.createTextNode(vnode)
case isFn(vnode.type):
return create(vnode.type({ ...props, children }))
default:
let elem = document.createElement(vnode.type)
isObj(props) && setProps(elem, props)
children.length > 0 && children.forEach(child =>
elem.appendChild(create(child))
)
return elem
}
}
let diff = (vnode, newVnode) => {
let type
switch (true) {
case vnode === newVnode:
return
case newVnode == null:
type = REMOVE
break
case vnode == null:
type = CREATE
break
case vnode.tagName !== newVnode.tagName:
type = REPLACE
break
case (isStr(vnode) || isNum(vnode) || isStr(newVnode) || isNum(newVnode)) && vnode != newVnode:
type = REPLACE
break
case !!(vnode.props || newVnode.props):
type = PROPS
break
}
let children = diffChildren(vnode, newVnode)
return { type, vnode, newVnode, ...children }
}
let patch = (node, patches, parent) => {
if (!patches) {
return node
}
let { vnode, newVnode, type, childrenType } = patches
let newNode
parent = node ? node.parentNode : parent
switch (type) {
case CREATE:
newNode = create(newVnode)
appendChild(parent, newNode)
break
case REMOVE:
removeChild(parent, node)
break
case REPLACE:
newNode = create(newVnode)
replaceChild(parent, newNode, node)
break
case PROPS:
applyProps(node, vnode.props, newVnode.props)
break
case WIDGET:
newVnode.update(vnode, node)
break
}
switch (childrenType) {
case REMOVE:
node.innerHTML = ''
break
case CREATE:
patches.newChildren.forEach(child => addChild(node, child))
break
case REPLACE:
let children = Array.prototype.slice.call(node.childNodes)
patches.childrenPatches.forEach((childPatches, index) => {
patch(children[index], childPatches, node)
})
break
}
return newNode || node
}
class Component {
constructor(props) {
this.props = props
this.state = {}
this.refs = {}
}
setState(nextState, callback) {
//do some thing
}
shouldComponentUpdate(nextProps, nextState) {
return true
}
componentWillUpdate(nextProps, nextState) {}
componentDidUpdate(prevProps, prevState) {}
componentWillReceiveProps(nextProps) {}
componentWillMount() {}
componentDidMount() {}
componentWillUnmount() {}
forceUpdate(callback) {
//do some thing
this.componentWillUpdate(nextProps, nextState)
//do some thing
this.componentDidUpdate(props, state)
if (isFn(callback)) {
callback()
}
}
}
autobind
& mixins
export let createClass = options => {
let mixins = options.mixins || []
let defaultProps = isFn(options.getDefaultProps) ? options.getDefaultProps() : null
let Klass = class extends Component {
constructor(props) {
super(props)
bindContext(this, Klass.prototype)
if (isObj(defaultProps)) {
this.componentWillReceiveProps(props)
}
if (isFn(this.getInitialState)) {
this.state = this.getInitialState()
}
}
}
combineMixins(Klass.prototype, mixins.concat(options))
if (isObj(options.statics)) {
for (let key in options.statics) {
if (options.statics.hasOwnProperty(key)) {
Klass[key] = options.statics[key]
}
}
}
return Klass
}
react-es3
、react-es5
、react-mobile
...document.createVirtualDOM
: 创建 virtual-domdocument.createVirtualComponent
: 创建 virtual-componentdocument.renderVirtualDOM
: 渲染 virtual-dom