雖然組件的原則就是模塊化,彼此之間相互獨(dú)立,但是有時(shí)候不同的組件之間可能會(huì)共用一些功能迂尝,共享一部分代碼鞠评。所以 React 提供了 mixins 這種方式來(lái)處理這種問(wèn)題茂蚓。
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = '';
},
setInterval: function(fn,time) {
this.intervals = setInterval(fn,time)
},
componentWillUnmount: function() {
clearTimeinterval(this.intervals)
}
};
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // Use the mixin
getInitialState: function() {
return {seconds: 0,
};
},
componentDidMount: function() {
this.setInterval(this.tick.bind(this), 1000); // Call a method on the mixin
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
上述是用es5語(yǔ)法寫(xiě)的mixin,每個(gè)組件都可以引入這個(gè)mixin在每個(gè)生命周期中調(diào)用剃幌。
Mixin 的特性一直廣泛存在于各種面向?qū)ο笳Z(yǔ)言聋涨。尤其在腳本語(yǔ)言中大都有原生支持,比如 Perl负乡、Ruby牍白、Python,甚至連 Sass 也支持抖棘。先來(lái)看一個(gè)在 Ruby 中使用 Mixin 的簡(jiǎn)單例子(裝個(gè)逼好嗎茂腥。。)
module D
def initialize(name)
@name = name
end
def to_s
@name
end
end
module Debug
include D
def who_am_i?
"#{self.class.name} (\##{self.object_id}): #{self.to_s}"
end
end
class Phonograph
include Debug
# ...
end
class EightTrack
include Debug
# ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Real Pillow")
puts ph.who_am_i? # Phonograph (#-72640448): West End Blues
puts et.who_am_i? # EightTrack (#-72640468): Real Pillow
一層套一層切省,類型方法的公用最岗。
寫(xiě)過(guò)css的同學(xué)都知道,sass這種預(yù)編譯的語(yǔ)言也可以寫(xiě)出mixins朝捆。
// triangle
@mixin triangle($direction, $size, $borderColor )
{ content:""; height: 0; width: 0;
@if $direction == top {
border-bottom:$size solid $borderColor;
border-left:$size dashed transparent;
border-right:$size dashed transparent; }
@else if $direction == right {
border-left:$size solid $borderColor;
border-top:$size dashed transparent;
border-bottom:$size dashed transparent;
} @else if $direction == bottom {
border-top:$size solid $borderColor;
border-left:$size dashed transparent;
border-right:$size dashed transparent;
} @else if $direction == left {
border-right:$size solid $borderColor;
border-top:$size dashed transparent;
border-bottom:$size dashed transparent; }
}
定義了一個(gè)實(shí)現(xiàn)三角形的mixins般渡,參數(shù)依次為尖角朝向,大小,邊緣顏色诊杆。
如何使用呢
.div{@include triangle}
封裝一個(gè)mixins函數(shù)
const mixin = function(obj, mixins) {
const newObj = obj;
newObj.prototype = Object.create(obj.prototype);
for (let prop in mixins) {
if (mixins.hasOwnProperty(prop)) {
newObj.prototype[prop] = mixins[prop];
}
}
return newObj;
}
const BigMixin = {
fly: () => {
console.log('I can fly');
}
};
const Big = function() {
console.log('new big');
};
Big.prototype.say = function(){
console.log('hello')
}
const FlyBig = mixin(Big, BigMixin);
const flyBig = new FlyBig(); // 'new big'
flyBig.fly(); // 'I can fly'
flyBig.say() // 'hello'
如果對(duì)create這種寫(xiě)法不太了解的歼捐,可以點(diǎn)這里.
我么來(lái)再來(lái)寫(xiě)一個(gè)稍微復(fù)雜的mixin
var anotherMixin = {
componentWillUpdate:function(newPro,newState){
this.refs.input.value=''
this.refs.input.focus()
console.log(newState)
}
change:function(e){
if(e.keyCode == 13 && e.target.value != ''){
! localStorage.getITem('list') ? localStorage.setItem('list',[e.value]) :
localStorage.getItem('list').indexOf(e.value) == -1 ?
this.setState({todos:this.state.todos.push(e.target.value),
count:this.state.count++}) : ''
}
setInterval: function(fn,time) {
this.intervals = setInterval(fn,time)
},
componentWillUnmount: function() {
clearTimeinterval(this.intervals)
}
}
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // Use the mixin
getInitialState: function() {
return {todos: [],count:0,step:1
};
},
componentDidMount: function() {
this.setInterval(this.tick.bind(this), 1000); // Call a method on the mixin
},
tick: function() {
if(thia.state.count >10){
this.setState({todos:[],count:1.step:this.state.step++})
}
},
render: function() {
return (
<p>當(dāng)前處于第{this.state.step}階段<p>
<input ref = 'input' onkeydown = this.change.bind(this)>
{this.state.todos.map (toto) => (
<div>'-----' todo '------'
) }
);
}
});
我們做了這樣一件事情,有一個(gè)任務(wù)列表晨汹,我們可以往里面添加事情豹储,每次到了10之后,step上升一步淘这,同時(shí)會(huì)根據(jù)localstorage檢測(cè)是否有重復(fù)事件的添加剥扣。
最后我們來(lái)看一下如何在python中使用mixin吧
class SimpleItemContainer(object):
def __init__(self, id, item_containers):
self.id = id
self.data = {}
for item in item_containers:
self.data[item.id] = item
class BetterSimpleItemContainer(object,SimpleItemContainer):
def __getitem__(self, id):
return self.data[id]
def __setitem__(self, id, value):
self.data[id] = value
def __delitem__(self, id):
del self.data[id]
def keys(self):
return self.data.keys()
其實(shí)就是一個(gè)類的繼承和復(fù)用而已,用到了一些特殊方法铝穷。