Have you ever been asked to build a rocket in a job interview?
I don’t want to complain because I’m the kind of interviewer who makes interviewees build rockets 🙂
This paper will analyze the causes of this situation from the underlying logic and put forward sincere suggestions.
Video tutorial
The village head specially recorded a supporting video and led everyone to pull out their mini Vue hand in hand:
From handwriting Vue to interview strategy analysis
Welcome to three small partners + attention, your encouragement is the biggest power I insist on ❤️
Why do interviews build rockets
Because the supply and demand of the market has changed, it used to be Spears, now it’s Mrs. Cow. It’s not like looking for a job 6 or 7 years ago. With more competitors, employers are more selective and choose more competent and motivated employees for the same amount of money. At the same time, interviewers found that everyone’s CV was the same: proficient in vUE framework and bucket, proficient in usingelement-ui
,iView
Such as component library, skilled useaxios
Get server-side data and so on. If the difficulty of the interview is not increased, it is difficult to distinguish between the competence of the interviewer and that of the interviewer.
How to deal with the problem of building rockets
For example, when the interviewer asks,
- Why do WE need data responsiveness?
vue
How is it implemented? - Why virtual
dom
?diff
What’s the process like?
Friends choose to find the answer, recite down, you can not solve the problem, because the answer is dead, can not stand scrutiny, a little questioning a few times will reveal.
I think we should take this opportunity to learn the source code, not only to find the answer to the question, deepen the UNDERSTANDING of THE API, but also to learn a lot of algorithms, design patterns and engineering knowledge, to improve the programming level is very helpful.
What if source code is difficult to learn
Many partners also want to read the source code to learn, but the source code is usually very large and complex, it is easy to discourage. I suggest you start with a mini implementation. Lay a good foundation first, after master to look at the source will be much simpler.
Try building a rocket
I’ll take Vue as an example, write a mini version, and then we’ll worry about building rockets.
Vue’s design philosophy
Before we start, let’s take a look at the design philosophy of Vue so that it will be easier to understand later:
Easy to understand, friendly, high-performance, easy to maintain, testable
Feel it in the code
Vue not used, 01-no-vue.html:
<div id="app"></div>
<script>
/ / requirements:
// 1. There is a title title that you want to display in the H3 tag
// The title will change after 2.2 seconds
const title = 'I'm a headline.'
const h3 = document.createElement('h3')
h3.textContent = title
app.appendChild(h3)
setTimeout(() = > {
h3.textContent = 'I still have the same title, but I've changed.'
}, 2000);
</script>
Copy the code
Features are:
- The user wants direct access to the DOM
- Dom manipulation is also part of the business
- The user’s mental burden is heavier, and the development efficiency is lower
Use Vue, 02-with-vue.html:
<div id="app">
<h3>{{title}}</h3>
</div>
<script src="http://unpkg.com/vue"></script>
<script>
/ / requirements:
// 1. There is a title title that you want to display in the H3 tag
// The title will change after 2.2 seconds
new Vue({
data() {
return {
title: 'I'm a headline.'}},mounted() {
setTimeout(() = > {
this.title = 'I still have the same title, but I've changed.'
}, 2000);
},
}).$mount('#app')
</script>
Copy the code
The important change is that our app is data-driven and avoids DOM manipulation, so our goal is clear:
- Be able to tell when the data has changed
- View updates can be performed after changes
Try building a wheel
Basic structure: Vue constructor and $mount method
<div id="app"></div>
<script>
function Vue(options) {}
Vue.prototype.$mount = function() {}
</script>
Copy the code
DefineProperty is used to realize data responsiveness and monitor data changes in data
function Vue(options) {
/ / response type
this.$options = options
this.$data = options.data()
observe(this.$data)
}
Vue.prototype.$mount = function () {}
// select * from obj
function observe(obj) {
Object.keys(obj).forEach(key= > {
defineReactive(obj, key, obj[key])
})
}
// Reactive intercepts object property access
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() { return val },
set(newVal) { val = newVal }
}
})
}
Copy the code
Mount: Prepares an update function for view initialization and subsequent updates
<script>
Vue.prototype.$mount = function (sel) {
// Create the update function
this.update = function () {
const child = this.$options.render.call(this)
const parent = document.querySelector(sel)
if (!this.isMounted) {
// init
parent.appendChild(child)
this.isMounted = true
if (this.$options.mounted) {
this.$options.mounted.call(this)}}else {
// update
parent.innerHTML = ' '
parent.appendChild(child)
}
}
this.update()
}
function observe(obj) {}
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {},
set(newVal) {
if(newVal ! == val) {// Trigger the updateapp.update(); }}})}</script>
Copy the code
<script>
const app = new Vue({
// Add the render function to render the DOM
render() {
const h3 = document.createElement('h3')
h3.textContent = this.$data.title
return h3
}
})
</script>
Copy the code
Problem: Each update is a full update to the view
Vnode based implementation to avoid full updates
<script>
Vue.prototype.$mount = function (sel) {
this.update = function () {
// Execute render to get the vnode
const vnode = this.$options.render.call(this.this.createElement)
if (!this.isMounted) {
// init patch: pass parent to dom
const parent = document.querySelector(sel)
this.patch(parent, vnode)
} else {
// Update patch: Pass two VNodes to diff
this.patch(this._vnode, vnode)
}
this._vnode = vnode
}
this.update()
}
// Add a vnode generator
Vue.prototype.createElement = function (tag, props, children) {
return { tag, props, children }
}
// Patch is used to convert vNode to DOM during initialization or update
Vue.prototype.patch = function (n1, n2) {
if (n1.nodeType) {
// init
const child = this.createElm(n2)
n1.appendChild(child)
n2.$el = child
} else {
// update}}// Create elements recursively
Vue.prototype.createElm = function (vnode) {
const {tag, props, children} = vnode
const el = document.createElement(tag)
/ / create the children
if (Array.isArray(children)) {
// element
children.forEach(child= > el.appendChild(createElm(children)))
} else {
// text
el.textContent = children
}
vnode.$el = el
return el
}
</script>
Copy the code
<script>
const app = new Vue({
// render returns vnode
render(h) {
return h('h3'.null.this.$data.title)
}
})
app.$mount('#app')
</script>
Copy the code
Update logic: Mainly depending on the children type of both parties, dom operation is performed specifically. Only the text in the test case is solved here
Vue.prototype.patch = function (n1, n2) { if (n1.nodeType) {} else { Dom const el = n2.$el = n1.$el // children update if (n1.tag === n2.tag) { If (typeof n1.children === 'string') {if (typeof n2.children === 'string') {// text update if (n1.children! == n2.children) { el.textContent = n2.children } } else { // replace text with elements } } else { if (typeof n2.children === 'string') { // replace elements with text } else { // update children } } } else { // replace } }
Copy the code
Now think about the answer strategy
Use four paragraphs: introduce the concept, explain the necessity, how to implement the source code, and how to use it in practice. Such as:
-
Why do WE need data responsiveness? How does it work?
Introduction to the concept: Data responsiveness is a mechanism for detecting changes in data in frameworks like MVVM, and varies among the three frameworks.
Necessity: The most important task of MVVM is to realize data-driven. To realize data-driven, it is necessary to know when data changes and respond to them, which requires a data-responsive mechanism.
Source code implementation: Vue 2.x mainly use defineProperty, vue 3.x mainly use Proxy (do not know not to mention). Take Vue 2.x as an example by traversing object attributes, defining GET /set, and doing attribute interception. In the future, data changes can be sensed and update functions can be called to update the view.
In practice: In practice, we pass in component props, methods, and data, all of which are handled responsively during Vue initialization, so that when they change, the view is re-rendered and updated. There are also special cases where new attributes are added or deleted and apis like vue. set/delete are required.
Of course, you still have to learn a lot of details, such as:
- How to notify views of updates
- How views are updated (virtual DOM and patch)
- What’s wrong with responsiveness in Vue 2.x (efficiency, extra API, array handling, etc.)
- Why do we need an API like vue. set/delete
You can see that all of them are derived from the point of responsiveness, and if you answer them properly, there’s basically no problem.
Example source code
Pay attention to the public number “village head learning front”
Video tutorial
The village head specially recorded a supporting video and led everyone to pull out their mini Vue hand in hand:
From handwriting Vue to interview strategy analysis
Welcome to three small partners + attention, your encouragement is the biggest power I insist on ❤️