1.需要の問題:
React-ant-design-mobile
APPプロジェクトを行うとき。ナビゲーションバーでリセットイベントが決定されたら、リストページを更新する必要があります。そして、これら2つのコンポーネントは互いに何の関係もありません。このとき、eventProxy
さまざまなコンポーネントを監視するメソッド機能が使用されます。
2、
- on、one:on関数とone関数は、サブスクライバーが対応するイベントを監視し、イベントに応答する関数をパラメーターとして使用するために使用されます。onとoneの唯一の違いは、1つを使用してサブスクライブする関数はonを使用している間、一度トリガーされます。サブスクライブされた関数は、イベントが発生するたびにトリガーされます。
- トリガー:トリガーは、パブリッシャーがイベントを公開するために使用し、最初のパラメーター(イベント名)以外の他のパラメーターを新しいパラメーターとして受け取り、1つ以上を使用してサブスクライブする機能をトリガーします。
- オフ:イベントにサブスクライブされているすべての関数を解放するために使用されます。
3.まず、eventProxy
ファイルをインポートする必要があります。
個別にファイルに入れるか、スクリプトを使用してインポートするか、重要なインポートを使用してeventProxyを使用します。
const eventProxy = {
onObj: {
},
oneObj: {
},
on: function (key, fn) {
if (this.onObj[key] === undefined) {
this.onObj[key] = [];
}
const args = [].concat(Array.prototype.slice.call(arguments, 1));
for (let i = 0; i < args.length; i++) {
this.onObj[key].push(args[i]);
}
},
one: function (key, fn) {
if (this.oneObj[key] === undefined) {
this.oneObj[key] = [];
}
this.oneObj[key].push(fn);
},
off: function (key) {
this.onObj[key] = [];
this.oneObj[key] = [];
},
trigger: function () {
let key, args;
if (arguments.length == 0) {
return false;
}
key = arguments[0];
args = [].concat(Array.prototype.slice.call(arguments, 1));
if (this.onObj[key] !== undefined
&& this.onObj[key].length > 0) {
for (let i in this.onObj[key]) {
this.onObj[key][i].call(null, args[i]);
}
}
if (this.oneObj[key] !== undefined
&& this.oneObj[key].length > 0) {
for (let i in this.oneObj[key]) {
this.oneObj[key][i].apply(null, args);
this.oneObj[key][i] = undefined;
}
this.oneObj[key] = [];
}
}
};
export default eventProxy;
4.使用する
- 監視する必要のあるコンポーネントメソッドの場合:
import eventProxy from '../../utils/eventProxy'
インポートファイル- 監視する必要がある方法で、
私はイベントを決定するためにここにいます
queryClick = () => {
eventProxy.trigger('query', 'list')
this.setState({
visible: false,
})
}
- 次に、対応するアクションを実行する必要があるコンポーネントでそれを使用します
- で
componentDidMount
、外出先での使用
componentDidMount() {
// 清除事件监听
eventProxy.on('query', () => {
this.getDynamicsList()
})
// eventProxy.on('clear', () => {
// this.getDynamicsList()
// })
}
使用後は、コンポーネントをアンインストールするときに必ずイベントリスナーをクリアしてください
componentWillUnmount = () => {
// 清除监听
eventProxy.off('query', '');
}
5.このようにして、さまざまなコンポーネントメソッドとイベントが接続されます。
参照できます-外観モード
外観モードは、比較的単純でユビキタスなモードです。アピアランスモードは、クライアントまたはサブシステムの呼び出しをより便利にする高レベルのインターフェイスを提供します。これ以上単純なコードではありません。
オブジェクト間の1対多の依存関係を定義する単純なサブスクリプションパブリッシャー/オブザーバーモデルを実装します。オブジェクトの状態が変化すると、それに依存するすべてのオブジェクトに通知されます。
実際、イベント関数をDOMノードにバインドしたことがある限り、オブザーバーモードを使用したことになります。
document.body.addEventListener( 'click'、function(){ alert(2); });
ただし、これはオブザーバーモードの最も単純な使用法です。多くのシナリオでは、ニーズを満たすためにいくつかのカスタムイベントを実装することがよくあります。
例:
あなたは会社に行って仕事に応募し、話をした後、hrはあなたにこう言います:「さて、あなたは戻って通知を待ちます!」。
このとき、1。会社の電話番号を尋ね、毎日
電話して結果を尋ねます。2。携帯電話番号を時間に任せて、彼があなたに電話するのを待ちます。
多くの場合、誰もが後者を選ぶと思います。
あなたが毎日hrに電話して彼を悩ませている場合、彼はもともとあなたを募集することを計画していたかもしれません、そして今彼はもうあなたを攻撃することを計画していません!
そして、この時点で、hrはパブリッシャーに相当し、あなたはサブスクライバーです!
さて、戻ってニュースを待つように頼むほとんどの人は助けにはなりません...
私はあなたが許可されていない場合でもあなたに通知しない会社にも遭遇しました!
では、単純なオブザーバーパターンをどのように実装する必要がありますか?
パブリッシャーを指定するには;
サブスクライバーに通知するコールバック関数を格納するためにパブリッシャーにキャッシュリストを追加します;(この会社の多くの人が応募します)
メッセージが最終的に公開されると、パブリッシャーはキャッシュリストをトラバースし、順番に格納されますサブスクライバーコールバック関数;(あなたが上またはあなたが上)
var event = {
}; //发布者(hr)
event.clietList = []; //发布者的缓存列表(应聘者列表)
event.listen = function(fn) {
//增加订阅者函数
this.clietList.push(fn);
};
event.trigger = function() {
//发布消息函数
for (var i = 0; i < this.clietList.length; i++) {
var fn = this.clietList[i];
fn.apply(this, arguments);
}
};
event.listen(function(time) {
//某人订阅了这个消息
console.log('正式上班时间:' + time);
});
event.trigger('2016/10',yes); //发布消息
//输出 正式上班时间:2016/10
到这里,我们已经实现了一个最简单的观察者模式了!
但是上面的函数其实存在一个问题,那就是发布者没办法选择自己要发布的消息类型!
比如这家公司同时在招php,web前端,如果使用上面的函数就没办法区分职位了!只能一次性把全部订阅者都发送一遍消息。
对上面的代码进行改写:
var event = {
}; //发布者(hr)
event.clietList = []; //发布者的缓存列表(应聘者列表)
event.listen = function(key, fn) {
//增加订阅者函数
if (!this.clietList[key]) {
this.clietList[key] = [];
}
this.clietList[key].push(fn);
};
event.trigger = function() {
//发布消息函数
var key = Array.prototype.shift.call(arguments),
fns = this.clietList[key];
for (var i = 0; i < fns.length; i++) {
var fn = fns[i];
fn.apply(this, arguments);
}
};
event.listen('web前端', fn1 = function(time) {
//小强订阅了这个消息。
console.log('姓名:小强');
console.log('正式上班时间:' + time);
});
event.listen('web前端', fn2 = function(time) {
//大大强订阅了这个消息
console.log('姓名:大大强');
console.log('正式上班时间:' + time);
});
//发布者发布消息
event.trigger('web前端','小强', '2016/10'); //姓名:小强 正式上班时间:2016/10
event.trigger('php','大大强', '2016/15'); //姓名:大大强 正式上班时间:2016/15
通过添加了一个key,我们实现了对职位的判断。
有了订阅事件,我们怎么能少了取消订阅事件呢?
event.remove = function(key, fn) {
var fns = this.clietList[key];
if (!fns) {
return false;
}
if (!fn) {
//如果没有传入fn回调函数,直接取消key对应消息的所有订阅
this.clietList[key] = [];
} else {
for (var i = 0; i < fns.length; i++) {
//遍历回调函数列表
var _fn = fns[i];
if (_fn === fn) {
fns.splice(i, 1); //删除订阅者的回调函数
}
}
}
};
//这时候必须指定回调函数,否则无法在remove函数中进行对比删除。
event.listen('web前端', fn1 = function(time) {
//小强订阅了这个消息。
console.log('姓名:小强');
console.log('正式上班时间:' + time);
});
event.listen('web前端', fn2 = function(time) {
//大大强订阅了这个消息
console.log('姓名:大大强');
console.log('正式上班时间:' + time);
});
event.remove('web前端',fn1);
//发布者发布消息
event.trigger('web前端','2016/10');
//输出 姓名:大大强 正式上班时间:2016/10
上記のコードを改善し、オブザーバーモードを実装するグローバルオブジェクトを作成し、
クロージャを使用してプライベート変数を実装し、必要なAPIのみをユーザーに公開します。
var event = (function() {
var clietList = []; //发布者的缓存列表(应聘者列表)
var listen = function(key, fn) {
//增加订阅者函数
if (!this.clietList[key]) {
this.clietList[key] = [];
}
this.clietList[key].push(fn);
};
var trigger = function() {
//发布消息函数
var key = Array.prototype.shift.call(arguments),
fns = this.clietList[key];
for (var i = 0; i < fns.length; i++) {
var fn = fns[i];
fn.apply(this, arguments);
}
};
var remove = function(key, fn) {
var fns = this.clietList[key];
if (!fns) {
return false;
}
if (!fn) {
//如果没有传入fn回调函数,直接取消key对应消息的所有订阅
this.clietList[key] = [];
} else {
for (var i = 0; i < fns.length; i++) {
//遍历回调函数列表
var _fn = fns[i];
if (_fn === fn) {
fns.splice(i, 1); //删除订阅者的回调函数
}
}
}
};
return{
listen:listen,
trigger:trigger,
remove:remove
}
})();
观察者模式进阶:
使用命名空间防止事件名冲突
实现先发布后订阅功能
[观察者模式引自原作者](https://segmentfault.com/a/1190000023447952)