Today we will discuss the vUE source code instructions and life cycle, we mainly over the next response type principle, here I would like to say one more sentence, learning source code is mainly to learn it inside the thought, thought is to achieve the algorithm, logic. So read the source code to improve our programming ability has a lot of help, learn what language is secondary, ok, now to see what needs to be prepared in front.
1. Demonstrate the instructions and life cycle of Vue2. X by hand, and simplify the rest
2. The content that has been implemented before will be used
- Build projects using Webpack and webpack-dev-server
- Create the study-directive directory
- cd study-directive
- npm init -yes
- npm i -D webpack@5 webpack-cli@3 webpack-dev-server@3
- Create a new webpack.config.js file
- Copy the following configuration to webpack.config.js
const path = require('path')
module.exports = {
/ / the entry
entry: './src/index.js'./ / export
output: {
// Virtual package path, that is, the folder is not actually generated, but on port 8080 virtual generation, not really physical generation
publicPath: 'xuni'.// The name of the packaged file
filename: 'bundle.js'
},
devServer: {
/ / the port number
port: 8080.// Static resources folder
contentBase: 'www'}}Copy the code
Create a new SRC /index.js file
alert(123)
Copy the code
Create a WWW /index.html file
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<h1>Hello!!!!!!</h1>
<script src="xuni/bundle.js"></script>
</body>
</html>
Copy the code
Add commands to package.json file:
{ "scripts": { "dev": "webpack-dev-server",}}Copy the code
- Terminal operation
npm run dev
- Access:
http://localhost:8080/
和http://127.0.0.1:8080/xuni/bundle.js
As you can seewww/index.html
和xuni/bundle.js
Contents of the document
precondition
- willVue2. X data response principleData responsively-related modules implemented in the
src
directory - Article address: juejin.cn/post/702634…
implementation
www/index.html
– Test data
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Initial - scale = 1.0 "> < title > Document < / title > < / head > < body > < div id =" app "> hello {{B.M.N}} < ul > < li > A < / li > < li > B < / li > < li > C < / li > < / ul > < input type = "text" v - model = "B.M.N" > < br > < / div > < button onclick = "add ()" > as I + 1 < / button > < script src="xuni/bundle.js"></script> <script> var vm = new Vue({ el: '#app', data: { a: 10, b: { m: { n: 7 } } }, watch: {{a () the console. The log (' a changed ')}}}) function to the add () {vm. B.M.N + +} < / script > < / body > < / HTML >Copy the code
src/index.js
–Vue
Hang to the global objectWindow
上
import Vue from './Vue'
window.Vue = Vue
Copy the code
src/Vue.js
–Vue
Class implementation (used to implement reactive binding of dataobserve
和Watcher
Module)
import Compiler from './Compiler'
import observe from './observe'
import Watcher from './Watcher'
export default class Vue {
constructor(options) {
// Save the options object as $options
this.$options = options || {}
/ / data
this._data = options.data || undefined
// Make the data responsive
observe(this._data)
// Default data becomes responsive, which is the life cycle
this._initData()
// Call default watch
this._initWatch()
// Template compilation
new Compiler(options.el, this)}_initData() {
var self = this
Object.keys(this._data).forEach((key) = > {
Object.defineProperty(self, key, {
get() {
return self._data[key]
},
set(newValue) {
self._data[key] = newValue
}
})
})
}
_initWatch() {
var self = this
var watch = this.$options.watch
Object.keys(watch).forEach((key) = > {
new Watcher(self, key, watch[key])
})
}
}
Copy the code
src/Compiler.js
– Template compilation
import Watcher from './Watcher'
export default class Compiler {
constructor(el, vue) {
/ / the vue instance
this.$vue = vue
/ / the mount point
this.$el = document.querySelector(el)
// If the user passes in a mount point
if (this.$el) {
// Call the function to make the node fragment, similar to tokens in Mustache
// Actually use AST, which is a lightweight fragment
let $fragment = this.node2Fragment(this.$el)
// Compile the template
this.compile($fragment)
// Replace the content to the tree
this.$el.appendChild($fragment)
}
}
node2Fragment(el) {
var fragment = document.createDocumentFragment()
var child
// Fragment all DOM nodes in el
while ((child = el.firstChild)) {
fragment.appendChild(child)
}
return fragment
}
compile(el) {
// Get the child element
var childNodes = el.childNodes
var self = this
var reg = / \ {\ {(. *) \} \} /
childNodes.forEach((node) = > {
var text = node.textContent
if (node.nodeType === 1) {
self.compileElement(node)
} else if (node.nodeType === 3 && reg.test(text)) {
let name = text.match(reg)[1]
self.compileText(node, name)
}
})
}
compileElement(node) {
// The convenience here is that you are not talking about HTML structures as strings, but as real property lists
var nodeAttrs = node.attributes
// Class array objects become arrays; [].slice.call(nodeAttrs).forEach((attr) = > {
// Parse instructions here
var attrName = attr.name
var attrValue = attr.value
// All commands start with v-
var dir = attrName.substring(2)
Attrname.startswith ('v-')
if (attrName.indexOf('v-') = = =0) {
// start with v-
if (dir === 'model') {
new Watcher(this.$vue, attrValue, (value) = > {
node.value = value
})
var v = this.getVueVal(this.$vue, attrValue)
node.value = v
node.addEventListener('input'.(e) = > {
var newVal = e.target.value
this.setVueVal(this.$vue, attrValue, newVal)
})
} else if (dir === 'if') {}}})}compileText(node, name) {
node.textContent = this.getVueVal(this.$vue, name)
new Watcher(this.$vue, name, (value) = > {
node.textContent = value // A view update is triggered})}getVueVal(vue, exp) {
var val = vue
exp = exp.split('. ')
exp.forEach((k) = > {
val = val[k]
})
return val
}
setVueVal(vue, exp, value) {
var val = vue
exp = exp.split('. ')
exp.forEach((k, i) = > {
if (i < exp.length - 1) {
val = val[k]
} else {
val[k] = value
}
})
}
}
Copy the code
Example source code:
Gitee.com/yokeney/vue…