current position:Home>[read the source code of ruokawa vision x] issue 23 | why can vue2 this directly obtain data and methods
[read the source code of ruokawa vision x] issue 23 | why can vue2 this directly obtain data and methods
2022-04-29 20:33:45【There's nothing left】
This article participated in by official account @ Ruokawa vision Weekly source code reading activity initiated , Click to learn more and participate together .
Interpretation principle
new Vue The general trend of :
initMethods
Realization this obtain methods The principle is methods The method traverses out , Mount to current vm For instance
Seeing this, there is not much doubt in logic , however bind
It takes more time to understand , Start to understand that functions hang directly to vm
Yes ,vm
Calling method , that this
It must point to vm
, Don't think bind Force binding this Why , Here's an interesting review this, Has tried the arrow function 、 Constructors 、 Closures and so on , None of the findings affected this Point to (this I haven't seen it for a while , Ha ha ha )
I read some answers in Chuange's discussion area , There is no way to delve into this problem , Finally, I would like to thank brother Chuan for his answer .
The conclusion is that bind Force binding this You can avoid this Lost problems , such as :
template
in@click
Bound events , It's useless herethis.someFunc
Called , And from the test results ,template
There is no extra processing in the compilation processthis
- deconstruction , No, this May directly report an error , For example, use this way in business :
const { validate } = this.$refs["formRef"]
function initMethods (vm, methods) {
var props = vm.$options.props;
for (var key in methods) {
// No function will warn
if (process.env.NODE_ENV !== 'production') {
if (typeof methods[key] !== 'function') {
warn(
"Method \"" + key + "\" has type \"" + (typeof methods[key]) + "\" in the component definition. " +
"Did you reference the function correctly?",
vm
);
}
// Unable to join props The property name on the has the same name
if (props && hasOwn(props, key)) {
warn(
("Method \"" + key + "\" has already been defined as a prop."),
vm
);
}
// Can't use $ perhaps _ start
if ((key in vm) && isReserved(key)) {
warn(
"Method \"" + key + "\" conflicts with an existing Vue instance method. " +
"Avoid defining component methods that start with _ or $."
);
}
}
// hold methods Hang all functions under to vm For instance
// The next step will be to data All properties of are linked to vm For instance , therefore this Access to data and methods Properties and methods in
vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
}
}
Copy code
initData
Handle data than methods It's a lot more complicated , Handle traversal mount to vm On , Also need to do responsive processing
summary :
- Handle data front , First turn off the dependency collector , The initialization phase does not deal with dependencies
- adopt Object.defineProperty Handle _data attribute , And hang the attribute to vm On , Ensure the timely update of data
- to data Object recursively creates an observer instance
function getData (data, vm) {
// #7573 disable dep collection when invoking data getters => Disable... When calling the data collector dep collect
// pushTarget There should be a parameter , Here is undefined, After being passed in, the current observable object is undefined
pushTarget();
try {
// good heavens , Don't look at the source code here , I really don't know the form of function data One more parameter
return data.call(vm, vm)
} catch (e) {
handleError(e, vm, "data()");
return {}
} finally {
// Pop from the collector stack push Of undefined, That is to open dep Collection function
popTarget();
}
}
Copy code
function initData (vm) {
var data = vm.$options.data;
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
// data The function must return An object , Otherwise, warn
if (!isPlainObject(data)) {
data = {};
process.env.NODE_ENV !== 'production' && warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
);
}
// proxy data on instance
var keys = Object.keys(data);
var props = vm.$options.props;
var methods = vm.$options.methods;
var i = keys.length;
while (i--) {
var key = keys[i];
// data Medium key Name and methods If it is repeated in, the console will warn
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {
warn(
("Method \"" + key + "\" has already been defined as a data property."),
vm
);
}
}
// data Medium key Name and props If it is repeated in, the console will warn
if (props && hasOwn(props, key)) {
process.env.NODE_ENV !== 'production' && warn(
"The data property \"" + key + "\" is already declared as a prop. " +
"Use prop default value instead.",
vm
);
} else if (!isReserved(key)) { // key A name cannot be named with $ perhaps _ start
// adopt Object.defineProperty Handle _data attribute , And hang the attribute to vm On
proxy(vm, "_data", key);
}
}
// observe data
// to data Create an observer instance , And added to the dependent collection ,set Property will trigger the dependency notify function
// If data The attribute in is an object , A new observer instance will be created recursively )
// If it is an array, it will traverse each item and create an observer instance , however defineProperty Can only act on functions , Direct assignment through array index value cannot trigger dependency collection
observe(data, true /* asRootData */);
}
Copy code
Implement a simple version
For reference only
// To create the agent
function proxy(target, source, key) {
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
console.log(" Read out key:"+key);
return this[source][key];
},
set(value) {
console.log(" Set up key:"+key+" The value is :"+value);
this[source][key] = value;
},
})
}
// The observer
function observe(value) {
if (!value || typeof value !== "object") {
return;
}
// return new Observer(value, vm);
}
function getData() {
// It will be closed temporarily dep collect
// Force binding this by vm, And pass in parameters
return vm.$options.data.call(vm,vm)
}
function initData(vm) {
var data = vm.$options.data;
// obtain data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
for (const key in data) {
// adopt proxy take data The properties on the proxy to vm On
proxy(vm, "_data", key);
}
// to data Create an observer instance
observe(data);
}
function initMethods(methods, vm) {
for (const key in methods) {
if (typeof methods[key] !== "function") return "ERROR";
// You have to use bind Force binding this
vm[key] = methods[key].bind(vm);
}
}
function Vue(options) {
this.$options = options;
this._init(options);
}
Vue.prototype._init = function (options) {
const vm = this;
vm._data=options.data;
initData(vm);
initMethods(options.methods, vm);
};
const _vm = new Vue({
data: {
msg: "hello",
name: " Zhao si ",
},
methods: {
say() {
console.log("say" + this.msg);
},
setMsg(msg) {
this.msg = msg;
}
},
});
_vm.say();
_vm.setMsg("hello world");
_vm.say();
Copy code
summary
Read the source code for the first time , Because I haven't used it vscode Debugging function of , Although I have seen brother Chuan's novice tutorial , But start debugging vue I was still confused when I was . Another is to use cli New project generated , There will be render Processing of , After adjusting for a long time, I didn't get to the point .
new Vue({
render: h => h(App),
}).$mount('#app')
Copy code
Refer to other students' articles , Just know that this writing can make the whole debugging process smoother , More agile :
new Vue({
data: {
msg: "Hello World",
},
methods: {
changeMsg() {
this.msg="Hello Vue.js";
}
},
}).$mount("#app");
Copy code
copyright notice
author[There's nothing left],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/04/202204292033398918.html
The sidebar is recommended
- Talking about nodejs server
- Node. js< I & gt—— Encounter node and repl usage
- Vue basic API: calculation attribute + filter + listener
- 1-stm32 + mn316 (nb-iot) remote upgrade OTA (self built Internet of things platform) - STM32 uses HTTP to download program files and upgrade programs through mn316 (MCU program rotation check and update)
- Vue Axios response interception
- vue3 ref
- How does Vue transfer the data from the parent component to the child component intact?
- The back-end interface developed by springboot in idea and the Vue front-end developed by vscode. How to integrate Vue code into springboot?
- Fried cold rice series 4: scope and closure in JavaScript
- Typescript type compatibility learning
guess what you like
Summary of bugs encountered in front-end development
Chrome developer tool: performance analysis using web panel
Collation of common semantic elements and global attributes in HTML
Life cycle in Vue
5.1 fear of traffic jam? With a budget of less than 100000, these cars with adaptive cruise make it easy for you to travel
Docker compose deploy nginx configure SSL
The content of element type “mapper“ must match “(cache-ref|cache|resultMap*|parameterMap*|sql*|inse
-CSS-
Vue uses two-way binding to implement the user registration page
Is Infiniti qx60 worth less than 400000 yuan? It depends on the discount
Random recommended
- "Element Fangjian: first heart version" public beta welfare release, go to the great God app to receive red envelopes and prizes
- What is the role of webpack cli in webpack packaging
- Vue3 configuration method using Axios
- How to configure Google reverse proxy on nginx server
- Volume comparison between Vue and react
- What are the three ways to define components in react
- How to install and configure the blogging program Typecho on the nginx server
- How to configure load balancing for TCP in nginx server
- How to configure nginx server under Windows system
- How to configure AB to do stress testing for nginx server
- Analysis of location configuration in nginx server
- How to integrate Linux and redmine into the redmine system
- How to build the production environment of nginx + PHP with PHP FPM
- How to optimize the performance of nginx supporting SSL
- How to configure nginx server to prevent flood attack
- [Axios learning] basic use of Axios
- [Axios learning] Axios request mode, concurrent request, global configuration, instance and interceptor
- Use the virtual queue implemented by list to view the first element of the queue in Python without taking it out
- This dependency was not found and to install it, you can run: NPM install score JS
- Front end serial communication
- leedcode. 203 remove linked list elements
- Dialogue with Liu Dayong, information director of Jiuyang shares: key elements of enterprise digital intelligence transformation
- JQuery gets the method summary of parent element, child element and brother element
- Web Security: analysis of DOM XSS vulnerability source code of jquery
- The sales volume of Genesys in China is 283, less than 300, and the domestic sales volume is dismal
- This beast was blessed with skills to test drive the DHT version of Harvard beast
- Bootstrap and jQuery implement tree structure
- Fried cold rice series 5: recursion in JavaScript?
- 2022 open source summer | serverless devs accompany you to "become stronger"
- How to create a high-performance full screen red envelope rain
- Detailed process of spring boot free HTTPS project configuration!
- Create a simple vue3 project
- How to create a simple react project
- Vue custom text background
- Front end HTML
- leetcode:462. Minimum number of moves to make array elements equal II [sort + find the middle]
- City selection (provincial and urban cascade) plug-in v-distpicker component details and a full set of usage
- How to use js to achieve such a drag and zoom effect
- Quick report ~ node JS 18 coming! Let's see what's new
- Easily manage projects using Vue UI graphical interface