Source code analysis Vue. js listener implementation tutorial, source code vue. js
Preface
I believe that when listening is made, of course, it will not be able to move away from the well-known Observer Model in the design model. For example, if your backyard is on fire, you must wait until the smoke is very bright and bright. But when you install a fire warning device, you will be notified immediately in the event of a fire. This is a typical observer model. There are also some other variants, such as the publish/subscribe mode.
We know that if we want to associate the data with the view, when the data changes, the view will be synchronized. Similarly, the view changes, and the data will also change. How does vue. js implement this? Let's unveil its secrets.
Demo:
<script src="../vue.js"> </script><div id="app"> <p> {{ message }} </p> <input v-model="message"></div><script type="text/javascript">new Vue({ el: '#app', data: { message: 'Hello Vue.js!' }});</script>set: function reactiveSetter(newVal) { var value = getter ? getter.call(obj) : val; if (newVal === value) { return; } if (setter) { setter.call(obj, newVal); } else { val = newVal; } childOb = observe(newVal); dep.notify();}
This code is called when the data attribute is parsed.Object.defineProperty
Method to configure the data attributes. If the attribute changes, notify sends a broadcast.
Dep.prototype.notify = function () { // stablize the subscriber list first var subs = toArray(this.subs); for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); }};
Notify eventually updates the subscribe (subscribe), so the above data change is the publisher. Subscribe is the instantiation object of Watcher class. During the instantiation, a callback function is passed in to execute update. vue gets a queue to execute the watcher update function. For details, refer to the source code.
Watcher.prototype.run = function () { …… if (value !== this.value || (isObject(value) || this.deep) && !this.shallow) { …… } else { this.cb.call(this.vm, value, oldValue); } } this.queued = this.shallow = false; } };
Watcher is instantiated in Directive (Directive) class, And the _ update function is responsible for updating
var watcher = this._watcher = new Watcher(this.vm, this.expression, this._update, // callback { filters: this.filters, twoWay: this.twoWay, deep: this.deep, preProcess: preProcess, postProcess: postProcess, scope: this._scope });
When parsing a template, Directive will be parsed, then bound, and watcher will be instantiated, so that the template-data will be associated.
Image Description
Observer Mode
The mvc or mvvm framework by Lin Zong also basically uses the observer mode, which is also very useful, especially in complicated systems.
With the observer mode, in typical ajax applications, the callback processing logic can be separated from the request, which makes the logic clearer. The following is a simple implementation of the publishing/subscription mode:
var PubSub = {};(function (q) { var topics = {}, subUid = -1; q.publish = function (topic) { if(!topics[topic]){ return false; } var subscribers = topics[topic], len = subscribers ? subscribers.length : 0; while(len--){ var args = Array.prototype.slice.call(arguments, 1); args.unshift(topic); subscribers[len].callback.apply(this, args); } return this; }; q.subscribe = function (topic, callback) { if(!topics[topic]){ topics[topic] = []; } var subuid = (++subUid).toString(); topics[topic].push({ token: subuid, callback: callback }); return subuid; }; q.unsubscribe = function (subid) { for(var k in topics){ if(topics[k]){ for(var i = 0, j = topics[k].length; i < j; i++){ if(topics[k][i].token === subid){ topics[k].splice(i, 1); return subid; } } } } return this; };})(PubSub);
This is a simple subscription and publishing system. Every time a subscriber is registered, the callback processing callback is saved in an array of dictionary objects. The key value of the dictionary object can be defined at will, you only need to match the key at release.
How to use it?
<script>var messageLogger = function(){ console.log(JSON.stringify(arguments)); };var subscription = PubSub.subscribe('/newMessage', messageLogger);// {"0":"/newMessage","1":"hello world"}PubSub.publish('/newMessage', 'hello world');// {"0":"/newMessage","1":["test","a","b","c"]}PubSub.publish('/newMessage', ['test', 'a', 'b', 'c']);// {"0":"/newMessage","1":{"sender":"hello world","body":"hey man"}}PubSub.publish('/newMessage', { sender: 'hello world', body: 'hey man'});PubSub.unsubscribe(subscription);PubSub.publish('/newMessage', ['test', 'a', 'b', 'c'], 1);</script>
The last one will not be printed because the subscription has been canceled.
Summary
The above is all the content of this article. I hope the content of this article will help you in your study or work. If you have any questions, please leave a message, thank you for your support.