anu, 讀作[安努],原意為蘇美爾的主神。
anu是我繼avalon之后又一個新框架(github倉庫為https://github.com/RubyLouvre/anu, 歡迎加星與試用)
此框架的創立之意有三:
-
提升性能, 雖然React的性能相對於傳統的MVVM框架是很厲害了,但近幾年冒出來的diff算法比官方版更優秀,官方版積重難返,很難短時期吸收這些成果。anu則小船好調頭,第一時間收納其中。性能是王道。天下武功,唯快不破。
-
壓縮體積。 React+React-dom加起來有三萬多行,這么大的體量任何code splitting與按需加載技術都無能為力,因此我們需要迷你版的體積。
-
卓越的瀏覽器兼容性。 React在生產環境中沒有用到什么新式偏門的API,因此本來就可以兼容到IE8之下。兼容性越好,我們的后顧之憂越少。
這三個特點都是為擴展React的通用性而努力。
在開發過程中,先是參考react-lite搞了一個版本,遇到問題后又根據preact搞了一版,第二版成功后命名為qreact,已經在公司的項目中用。
第二版的特點是preact改+preact.compat改+自創事件系統+diff機制改。反正經過這次研發后,我們已經掌握了React的許多機制,但是還沒有吃透preact的diff。
不過騰出時間來后,開始第三版,就是現在開源出來的anu,它大部分機制是自創的,diff機制采取react-lite。性能比第二代qreact強許多。
以下是成品anu的賣點:
- 支持React的無狀態組件,純組件,高階組件,受控組件與非受控組件,
- 命名空間就是React,此外還暴露了另一個別名ReactDOM在window上,省得在webpack上使用別名了。
- 體積非常小(1700行相對於react+react-dom的3萬行)
- 性能是官方React的兩倍以上 測試頁面、 結果統計
- 生命周期函數的參數與官方保持一致
- 直接與react-redux, react-router-dom, react-router-redux混用
- 支持后端渲染
- 支持官方的chrome DevTools
如果你想將它應用於IE8或之下,需要以下補丁
低版本瀏覽器可能需要以下 語言補丁
或者直接使用polyfill.js https://github.com/RubyLouvre/anu/tree/master/dist/polyfill.js
詳細用法與示例見官網 ,以下我會寫文章展開介紹它的用法。下面是一些小例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script type='text/javascript' src="./dist/React.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.24.0/babel.js"></script>
<script type="text/babel" >
class A extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
aaa: {
a: 7
}
}
}
click() {
this.setState(function(state){
state.aaa.a = 8
})
}
render() {
return <div onClick={this.click.bind(this) }>{this.state.aaa.a}</div>
}
}
window.onload = function () {
ReactDOM.render(<A />, document.getElementById('example'))
}
</script>
</head>
<body>
<div>這個怎么點擊也不會變</div>
<blockquote id='example'></blockquote>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script type='text/javascript' src="./dist/React.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.24.0/babel.js"></script>
<script type="text/babel" >
class Select extends React.Component{
constructor(props){
super(props)
this.state = {
value: props.value
}
this.onUpdate = props.onUpdate
this.onChange = this.onChange.bind(this)
}
componentWillReceiveProps(props){
this.state = { //更新自己
value: props.value
}
}
onChange(e){//讓父組件更新自己
this.onUpdate(e.target.value)
}
render(){
return <select value={this.state.value} onChange={this.onChange}>
<option>北京</option>
<option>南京</option>
<option>東京</option>
</select>
}
}
class App extends React.Component{
constructor(props){
super(props)
this.state = {
value: '南京'
}
}
onUpdate(value){ //讓子組件調用這個父組件的方法
this.setState({
value: value
})
}
onChange(e){
this.onUpdate(e.target.value)
}
render(){
return <div><Select onUpdate={this.onUpdate.bind(this)} value={this.state.value} /><input value={this.state.value} onChange={this.onChange.bind(this)} /></div>
}
}
window.onload = function () {
ReactDOM.render(<App />,
document.getElementById('example'))
}
</script>
</head>
<body>
<div>測試</div>
<blockquote id='example'></blockquote>
</body>
</html>
與Redux使用的例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script type='text/javascript' src="./dist/React.js"></script>
<script src="https://cdn.bootcss.com/redux/3.6.0/redux.js"></script>
<script src="./test/babel.js"></script>
<script type='text/babel'>
var addTodoActions = function (text) {
return {
type: 'add_todo',
text: text
};
}
var todoReducer = function (state, action) {
if (typeof state === 'undefined') {
return [];
}
switch (action.type) {
case 'add_todo':
return state.slice(0).concat({
text: action.text,
completed: false
});
break;
default:
return state;
}
};
var store = Redux.createStore(todoReducer);
class App extends React.Component {
constructor(props){
super(props)
this.state = {
items: store.getState()
}
this.onChange = this.onChange.bind(this)
this.handleKeyUp = this.handleKeyUp.bind(this)
this.handleAdd = this.handleAdd.bind(this)
}
componentDidMount(){
var unsubscribe = store.subscribe(this.onChange);
}
onChange(){
this.setState({
items: store.getState()
});
}
handleKeyUp(e){
if(e.which === 13){
this.handleAdd()
}
}
handleAdd(){
var input = this.refs.todo
var value = input.value.trim();
if(value)
store.dispatch(addTodoActions(value));
input.value = '';
}
render(){
return (
<div>
<input ref="todo" type="text" placeholder="輸入todo項" style={{marginRight:'10px'}} onKeyUp={this.handleKeyUp} />
<button onClick={this.handleAdd}>點擊添加</button>
<ul>
{this.state.items.map(function(item){
return <li>{item.text}</li>;
})}
</ul>
</div>
);
}
};
ReactDOM.render(
<App />,
document.getElementById('example')
);
</script>
</head>
<body>
<div>測試</div>
<blockquote id='example'></blockquote>
</body>
</html>