แนะนำ
โหมดผู้สังเกตการณ์เรียกอีกอย่างว่าเผยแพร่/สมัครสมาชิก มันกำหนดความสัมพันธ์แบบหนึ่งถึงหลายคนทำให้วัตถุผู้สังเกตการณ์หลายคนสามารถฟังวัตถุหัวข้อในเวลาเดียวกัน เมื่อสถานะของวัตถุหัวข้อนี้เปลี่ยนแปลงวัตถุผู้สังเกตการณ์ทั้งหมดจะได้รับแจ้งเพื่อให้พวกเขาสามารถอัปเดตตัวเองโดยอัตโนมัติ
ประโยชน์ของการใช้โหมดผู้สังเกตการณ์:
1. รองรับการสื่อสารออกอากาศอย่างง่ายและแจ้งวัตถุที่สมัครสมาชิกทั้งหมดโดยอัตโนมัติ
2. หลังจากโหลดหน้าเว็บวัตถุเป้าหมายสามารถมีความสัมพันธ์แบบไดนามิกกับผู้สังเกตการณ์ซึ่งเพิ่มความยืดหยุ่น
3. ความสัมพันธ์ที่มีเพศสัมพันธ์แบบนามธรรมระหว่างวัตถุเป้าหมายและผู้สังเกตการณ์สามารถขยายและนำกลับมาใช้ใหม่ได้
ข้อความ (เวอร์ชัน 1)
การดำเนินการตามรูปแบบผู้สังเกตการณ์ใน JS นั้นทำได้ผ่านการโทรกลับ ก่อนอื่นให้กำหนดวัตถุ PubSub ซึ่งมี 3 วิธี: การสมัครสมาชิกยกเลิกการสมัครและเผยแพร่
การคัดลอกรหัสมีดังนี้:
var pubsub = {};
(ฟังก์ชั่น (q) {
topics var = {}, // อาร์เรย์ที่เก็บไว้โดยฟังก์ชันการโทรกลับ
subuid = -1;
// วิธีการเผยแพร่
Q.Publish = ฟังก์ชั่น (หัวข้อ, args) {
ถ้า (! หัวข้อ [หัวข้อ]) {
กลับเท็จ;
-
settimeout (function () {
สมาชิก VAR = หัวข้อ [หัวข้อ]
LEN = สมาชิก? สมาชิกความยาว: 0;
ในขณะที่ (เลน-) {
สมาชิก [len] .func (หัวข้อ, args);
-
}, 0);
กลับมาจริง;
-
// วิธีการสมัครสมาชิก
Q.Subscribe = ฟังก์ชั่น (หัวข้อ, func) {
ถ้า (! หัวข้อ [หัวข้อ]) {
หัวข้อ [หัวข้อ] = [];
-
var token = (++ subuid) .tostring ();
หัวข้อ [หัวข้อ] .push ({
โทเค็น: โทเค็น
func: func
-
โทเค็นกลับมา;
-
// วิธีการยกเลิกการสมัคร
Q.UnSubscribe = ฟังก์ชั่น (โทเค็น) {
สำหรับ (var m ในหัวข้อ) {
ถ้า (หัวข้อ [m]) {
สำหรับ (var i = 0, j = หัวข้อ [m] .length; i <j; i ++) {
if (หัวข้อ [m] [i] .token === โทเค็น) {
หัวข้อ [m] .splice (i, 1);
โทเค็นกลับมา;
-
-
-
-
กลับเท็จ;
-
} (pubsub));
วิธีใช้เป็นดังนี้:
การคัดลอกรหัสมีดังนี้:
// มาสมัครสมาชิกหนึ่งคน
pubsub.subscribe ('ตัวอย่าง 1', ฟังก์ชั่น (หัวข้อ, ข้อมูล) {
console.log (หัวข้อ + ":" + data);
-
// ประกาศการเปิดตัว
pubsub.publish ('ตัวอย่าง 1', 'Hello World!');
pubsub.publish ('ตัวอย่าง 1', ['ทดสอบ', 'a', 'b', 'c']);
pubsub.publish ('ตัวอย่าง 1', [{'color': 'blue'}, {'text': 'hello'}]);
แล้วล่ะ? ใช้งานไม่ได้เลยเหรอ? แต่มีปัญหากับวิธีนี้นั่นคือไม่มีวิธีที่จะยกเลิกการสมัคร หากคุณต้องการยกเลิกการสมัครคุณต้องระบุชื่อของการยกเลิกการสมัครดังนั้นลองไปที่เวอร์ชันอื่น:
การคัดลอกรหัสมีดังนี้:
// กำหนดการสมัครสมาชิกให้กับตัวแปรเพื่อยกเลิกการสมัคร
var testsubscription = pubsub.subscribe ('ตัวอย่าง 1', ฟังก์ชั่น (หัวข้อ, ข้อมูล) {
console.log (หัวข้อ + ":" + data);
-
// ประกาศการเปิดตัว
pubsub.publish ('ตัวอย่าง 1', 'Hello World!');
pubsub.publish ('ตัวอย่าง 1', ['ทดสอบ', 'a', 'b', 'c']);
pubsub.publish ('ตัวอย่าง 1', [{'color': 'blue'}, {'text': 'hello'}]);
// unsubscription
settimeout (function () {
pubsub.unsubscribe (testsubscription);
}, 0);
// เผยแพร่อีกครั้งเพื่อตรวจสอบว่าข้อมูลยังสามารถส่งออกได้หรือไม่
pubsub.publish ('ตัวอย่าง 1', 'สวัสดีอีกครั้ง! (สิ่งนี้จะล้มเหลว)');
เวอร์ชัน 2
นอกจากนี้เรายังสามารถใช้คุณสมบัติของต้นแบบเพื่อใช้รูปแบบผู้สังเกตการณ์รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชัน Observer () {
this.fns = [];
-
observer.prototype = {
สมัครสมาชิก: ฟังก์ชั่น (fn) {
this.fns.push (fn);
-
ยกเลิกการสมัคร: ฟังก์ชั่น (fn) {
this.fns = this.fns.filter (
ฟังก์ชั่น (EL) {
ถ้า (el! == fn) {
return el;
-
-
-
-
อัปเดต: ฟังก์ชัน (o, thisobj) {
var scope = thisobj || หน้าต่าง;
this.fns.foreach (
ฟังก์ชั่น (EL) {
El.Call (ขอบเขต, O);
-
-
-
-
//ทดสอบ
var o = ผู้สังเกตการณ์ใหม่;
var f1 = function (data) {
console.log ('Robbin:' + data + ', ทำงานได้อย่างรวดเร็ว!');
-
var f2 = function (data) {
console.log ('Randall:' + data + 'พบว่าเขาได้รับเงินเดือนพิเศษ!');
-
O.Subscribe (F1);
O.Subscribe (F2);
O.update ("ทอมกลับมาแล้ว!")
// ยกเลิกการสมัครเป็น F1
O.Unsubscribe (F1);
// ตรวจสอบอีกครั้ง
O.update ("ทอมกลับมาแล้ว!");
หากไม่พบฟังก์ชั่นตัวกรองหรือ foreach อาจเป็นเพราะเบราว์เซอร์ของคุณไม่ใหม่พอและไม่รองรับฟังก์ชั่นมาตรฐานใหม่ในขณะนี้ คุณสามารถกำหนดด้วยตัวเองด้วยวิธีต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
if (! array.prototype.foreach) {
array.prototype.foreach = function (fn, thisobj) {
var scope = thisobj || หน้าต่าง;
สำหรับ (var i = 0, j = this.length; i <j; ++ i) {
fn.call (ขอบเขต, [i], i, this);
-
-
-
if (! array.prototype.filter) {
array.prototype.filter = function (fn, thisobj) {
var scope = thisobj || หน้าต่าง;
var a = [];
สำหรับ (var i = 0, j = this.length; i <j; ++ i) {
ถ้า (! fn.call (ขอบเขต, [i], i, this)) {
ดำเนินการต่อ;
-
A.push (นี่ [i]);
-
กลับ A;
-
-
เวอร์ชัน 3
หากคุณต้องการให้วัตถุหลายชิ้นมีฟังก์ชั่นของการสมัครสมาชิกผู้สังเกตการณ์เราสามารถกำหนดฟังก์ชั่นทั่วไปจากนั้นใช้ฟังก์ชั่นของฟังก์ชั่นกับวัตถุที่ต้องใช้ฟังก์ชันผู้สังเกตการณ์ รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
// รหัสสากล
var observer = {
// การสมัครสมาชิก
addSubsCriber: ฟังก์ชั่น (โทรกลับ) {
this.subscribers [this.subscribers.length] = การโทรกลับ;
-
// unsubscription
ลบ.
สำหรับ (var i = 0; i <this.subscribers.length; i ++) {
if (this.subscribers [i] === การโทรกลับ) {
ลบ (this.subscribers [i]);
-
-
-
//ปล่อย
เผยแพร่: ฟังก์ชั่น (อะไร) {
สำหรับ (var i = 0; i <this.subscribers.length; i ++) {
if (typeof this.subscribers [i] === 'function') {
this.subscribers [i] (อะไร);
-
-
-
// ทำให้วัตถุ o มีฟังก์ชั่นผู้สังเกตการณ์
Make: function (o) {
สำหรับ (var i ในนี้) {
o [i] = สิ่งนี้ [i];
O.Subscribers = [];
-
-
-
จากนั้นสมัครสมาชิก 2 วัตถุ Blogger และผู้ใช้ให้ใช้วิธีการ observer.make เพื่อให้วัตถุทั้งสองนี้มีฟังก์ชั่นผู้สังเกตการณ์รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้:
var blogger = {
แนะนำ: ฟังก์ชั่น (id) {
var msg = 'dudu ที่แนะนำโพสต์:' + id;
this.publish (msg);
-
-
var user = {
โหวต: ฟังก์ชั่น (id) {
var msg = 'มีคนโหวต! id =' + id;
this.publish (msg);
-
-
observer.make (บล็อกเกอร์);
observer.make (ผู้ใช้);
วิธีการใช้งานค่อนข้างง่าย สมัครสมาชิกฟังก์ชั่นการโทรกลับที่แตกต่างกันเพื่อให้คุณสามารถลงทะเบียนกับวัตถุผู้สังเกตการณ์ที่แตกต่างกัน (หรือวัตถุผู้สังเกตการณ์หลายรายการสามารถลงทะเบียนได้ในเวลาเดียวกัน):
การคัดลอกรหัสมีดังนี้:
var tom = {
อ่าน: ฟังก์ชั่น (อะไร) {
console.log ('ทอมเห็นข้อความต่อไปนี้:' + อะไร)
-
-
var mm = {
แสดง: ฟังก์ชั่น (อะไร) {
console.log ('mm เห็นข้อความต่อไปนี้:' + อะไร)
-
-
// สมัครสมาชิก
Blogger.addsubscriber (tom.read);
Blogger.addsubscriber (MM.Show);
Blogger.recommend (123); // โทรเผยแพร่
// unsubscription
blogger.removesubscriber (mm.show);
Blogger.recommend (456); // โทรเผยแพร่
// สมัครสมาชิกวัตถุอื่น
user.addsubscriber (mm.show);
user.vote (789); // โทรเผยแพร่
เวอร์ชัน jQuery
ตามฟังก์ชั่นเปิด/ปิดที่เพิ่มใน jQuery เวอร์ชัน 1.7 เรายังสามารถกำหนดผู้สังเกตการณ์ของเวอร์ชัน jQuery:
การคัดลอกรหัสมีดังนี้:
(ฟังก์ชั่น ($) {
var o = $ ({});
$ .subscribe = function () {
o.on.apply (o, อาร์กิวเมนต์);
-
$ .unsubscribe = function () {
o.off.apply (o, อาร์กิวเมนต์);
-
$ .publish = function () {
o.trigger.apply (o, อาร์กิวเมนต์);
-
} (jQuery));
วิธีการโทรนั้นง่ายกว่าสามเวอร์ชันข้างต้น:
การคัดลอกรหัสมีดังนี้:
// ฟังก์ชั่นการโทรกลับ
มือจับฟังก์ชั่น (E, A, B, C) {
// `e` เป็นวัตถุเหตุการณ์ไม่จำเป็นต้องให้ความสนใจ
console.log (a + b + c);
-
// การสมัครสมาชิก
$ .subscribe ("/some/topic", handle);
//ปล่อย
$ .publish ("/some/topic", ["a", "b", "c"]); // output ABC
$ .UnSubscribe ("/some/topic", handle); // ยกเลิกการสมัคร
// การสมัครสมาชิก
$ .subscribe ("/บางส่วน/หัวข้อ", ฟังก์ชั่น (e, a, b, c) {
console.log (a + b + c);
-
$ .publish ("/some/topic", ["a", "b", "c"]); // output ABC
// ยกเลิกการสมัคร (UNSubscribe ใช้ชื่อ/บางชื่อ/หัวข้อไม่ใช่ฟังก์ชันการโทรกลับซึ่งแตกต่างจากตัวอย่างของเวอร์ชัน 1
$ .UnSubscribe ("/บางส่วน/หัวข้อ");
จะเห็นได้ว่าการสมัครสมาชิกและยกเลิกการสมัครใช้ชื่อสตริงไม่ใช่ชื่อฟังก์ชันการโทรกลับดังนั้นแม้ว่าฟังก์ชั่นที่ไม่ระบุชื่อที่เข้ามาจะถูกส่งผ่านเราสามารถยกเลิกการสมัคร
สรุป
การใช้ผู้สังเกตการณ์คือ: เมื่อวัตถุเปลี่ยนไปเปลี่ยนวัตถุอื่น ๆ ในเวลาเดียวกันและไม่ทราบว่าต้องเปลี่ยนวัตถุจำนวนเท่าใดควรพิจารณาใช้โหมดผู้สังเกตการณ์
โดยรวมแล้วสิ่งที่รูปแบบผู้สังเกตการณ์ทำคือ decouple ทำให้ทั้งสองด้านของการมีเพศสัมพันธ์นั้นขึ้นอยู่กับสิ่งที่เป็นนามธรรมมากกว่าคอนกรีต สิ่งนี้ทำให้เป็นไปได้ว่าการเปลี่ยนแปลงของกันและกันจะไม่ส่งผลกระทบต่อการเปลี่ยนแปลงในอีกด้านหนึ่ง