Jiangcheng Cheerful Pea: Personal homepage
Personal column :《VUE》《javaScript》
Personal website : “Jiangcheng Cheerful Pea”
The ideal of life is for an ideal life!
Table of Contents
? Column introduction
1. What is two-way binding?
2. What is the principle of two-way binding?
Understanding ViewModel
3. Implement two-way binding
accomplish
CompileCompile
dependency collection
?Write at the end
? Column Introduction
Welcome to the front-end entry journey! This column is created for readers who are interested in web development and have just started learning front-end. Whether you are a beginner or a developer with some basic knowledge, we will provide you with a systematic and friendly learning platform here. We update it in the form of questions and answers to present you with selected front-end knowledge points and best practices. By explaining concepts in simple and easy-to-understand terms and providing practical examples and exercises, you can gradually build a solid foundation. Whether it is HTML, CSS, JavaScript or the latest front-end frameworks and tools, we will provide you with rich content and practical skills to help you better understand and apply various technologies in front-end development.
At the same time, we will also pay attention to the latest front-end trends and developments. As Web technology continues to evolve, front-end development is also constantly innovating. We will introduce the latest front-end frameworks, tools and technologies in a timely manner so that you can stay at the forefront and keep pace with the times. By mastering the latest front-end technologies, you will be able to become more competitive in the highly competitive field of web development.
1. What is two-way binding
Let’s first switch from one-way binding to one-way binding. It is very simple. It is to bind
Model
toView
. When we useJavaScript
code to updateModel
,View
will automatically update the two-way binding. It is easy to think of it. On the basis of one-way binding, the user updates theView
, the data ofModel
is also automatically updated. This is an example of two-way binding.
When the user fills in the form, the status of View
is updated. If the status of Model
can be automatically updated at this time, it is equivalent to us putting Model The two-way binding relationship between code> and
View
is as follows:
2. What is the principle of two-way binding
We all know that Vue
is a framework for two-way data binding. Two-way binding consists of three important parts.
- Data layer (Model): application data and business logic
- View layer (View): application display effect, various UI components
- Business logic layer (ViewModel): the core of the framework encapsulation, which is responsible for associating data with views
The above layered architecture solution can be called a professional term: MVVM
The core function of the control layer here is "two-way data binding". Naturally, we only need to understand what it is to further understand the principles of data binding
Understanding ViewModel
Its main responsibilities are:
- Update view after data changes
- Update data after view changes
Of course, it also consists of two main parts
- Observer: monitors the properties of all data
- Compiler: scans and parses the instructions of each element node, replaces data according to the instruction template, and binds the corresponding update function
3. Implement two-way binding
Let’s take Vue
as an example. Let’s first take a look at the two-way binding process in Vue
.
new Vue()
first performs initialization and performs responsive processing ondata
. This process occurs inObserve
- At the same time, compile the template, find the dynamically bound data, obtain and initialize the view from
data
, this process occurs inCompile
- Define an update function and
Watcher
at the same time. When the corresponding data changes in the future,Watcher
will call the update function.- Since a
key
ofdata
may appear multiple times in each view, eachkey
requires a housekeeperDep
To manage multipleWatchers
- Once the data in data changes in the future, the corresponding
Dep
will be found first, and allWatcher
will be notified to execute the update function.
The flow chart is as follows:
implementation
Let’s start with a constructor: perform initialization and perform responsive processing on data
class Vue { constructor(options) { this.$options = options; this.$data = options.data; //Responsive processing of data options observe(this.$data); // Agent data to vm proxy(this); //Execute compilation new Compile(options.el, this); } }
Perform responsive specific operations on the data
option
function observe(obj) { if (typeof obj !== "object" || obj == null) { return; } new Observer(obj); } class Observer { constructor(value) { this.value = value; this.walk(value); } walk(obj) { Object.keys(obj).forEach((key) => { defineReactive(obj, key, obj[key]); }); } }
CompileCompile
Scan and parse the instructions of each element node, replace the data according to the instruction template, and bind the corresponding update function
class Compile { constructor(el, vm) { this.$vm = vm; this.$el = document.querySelector(el); // Get dom if (this.$el) { this.compile(this.$el); } } compile(el) { const childNodes = el.childNodes; Array.from(childNodes).forEach((node) => { // Traverse child elements if (this.isElement(node)) { // Determine whether it is a node console.log("Compile element" + node.nodeName); } else if (this.isInterpolation(node)) { console.log("Compile interpolation? This" + node.textContent); // Determine whether it is interpolated text {<!-- -->{}} } if (node.childNodes & amp; & amp; node.childNodes.length > 0) { // Determine whether there are child elements this.compile(node); // Recursively traverse child elements } }); } isElement(node) { return node.nodeType == 1; } isInterpolation(node) { return node.nodeType == 3 & amp; & amp; /\{\{(.*)\}\}/.test(node.textContent); } }
Dependency Collection
A certain key
in data
will be used in the view, which is called dependency. The same key
may appear multiple times, and each time it needs to be collected and maintained using a Watcher
. This process is called dependent collection of multiple Watcher
requires a Dep
to manage, and will be notified by the Dep
system when it needs to be updated.
Implementation ideas
defineReactive
creates oneDep
instance for eachkey
- When initializing the view, read a
key
, such asname1
, and create awatcher1
- Since the
getter
method ofname1
is triggered,watcher1
is added to the Dep corresponding toname1
- When
name1
is updated andsetter
is triggered, it can be notified through the correspondingDep
to manage allWatcher
updates
//Responsible for updating the view class Watcher { constructor(vm, key, updater) { this.vm = vm this.key = key this.updaterFn = updater // When creating an instance, assign the current instance to the Dep.target static property Dep.target = this // Read the key and trigger get vm[key] // Blanking Dep.target = null } //The dom update function will be executed in the future, called by dep update() { this.updaterFn.call(this.vm, this.vm[this.key]) } }
DeclarationDep
class Dep { constructor() { this.deps = []; // Dependency management } addDep(dep) { this.deps.push(dep); } notify() { this.deps.forEach((dep) => dep.update()); } }
Triggers getter
when creating watcher
class Watcher { constructor(vm, key, updateFn) { Dep.target = this; this.vm[this.key]; Dep.target = null; } }
Dependency collection, create Dep
instance
function defineReactive(obj, key, val) { this.observe(val); const dep = new Dep(); Object.defineProperty(obj, key, { get() { Dep.target & amp; & amp; dep.addDep(Dep.target);// Dep.target is the Watcher instance return val; }, set(newVal) { if (newVal === val) return; dep.notify(); // Notify dep to execute the update method }, }); }
? Write at the end
Please feel free to give me some advice, comment below or send me a private message. Thank you very much.
? I think a certain part of my design is too cumbersome. Is there a simpler or higher-quality packaging method?
? Think some of my code is too old and can provide new API or the latest syntax?
? Don’t understand some of the content in the article
?Answer some questions in my article
? Think that some interactions and functions need to be optimized, and find bugs
? Want to add new features and have better suggestions for the overall design and appearance?
Finally, thank you for your patience in watching. Now that we are here, click Like and go!