1. КМБ
One Dependency:There is just one build dependency.
No Configuration Required: You don't need to configure anything.
No Lock-In: You can “eject” to a custom setup at any time.
2. DOM
SFC -> JS
<template>
<div id="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style scoped>
#hello {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
}
</style>
Vue template compiler
<div id="hello">
<h1>{{ msg }}</h1>
</div>
render
function render() {
with(this) {
return _c('div',{attrs:{"id":"hello"}},[_c('h1',[_v(_s(msg))])])
}
}
// staticRenderFns:[]
render
render: function (createElement) { // or h
return createElement('div',
{
attrs: {"id": "hello"}
},
[
createElement('h1',
[
Vue.createTextVNode(_toString(msg)) // _v(_s(msg))
]
)
]
)
}
Vue template compiler
<div>
<p>Hello!</p>
</div>
staticRenderFns
_m(0): function anonymous() {
with(this){return _c('div',[_c('p',[_v("Hello!")])])}
}
export default class VNode {
tag: string | void;
data: VNodeData | void;
children: ?Array<VNode>
text: string | void;
elm: Node | void;
ns: string | void;
context: Component | void; // rendered in this component's scope
key: string | number | void;
componentOptions: VNodeComponentOptions | void;
componentInstance: Component | void; // component instance
parent: VNode | void; // component placeholder node
//...
/**
* Virtual DOM patching algorithm based on Snabbdom by
* Simon Friis Vindum (@paldepind)
* Licensed under the MIT License
* https://github.com/paldepind/snabbdom/blob/master/LICENSE
*
* modified by Evan You (@yyx990803)
*
* Not type-checking this because this file is perf-critical and the cost
* of making flow understand it is not worth it.
*/
// vue/src/core/vdom/patch.js
function createElm (
// ...
vnode.elm = vnode.ns
? nodeOps.createElementNS(vnode.ns, tag)
: nodeOps.createElement(tag, vnode)
export function createPatchFunction (backend) {
const { modules, nodeOps } = backend
// ...
// vue/src/platforms/web/runtime/node-ops.js
export function createElement (tagName: string, vnode: VNode): Element {
const elm = document.createElement(tagName)
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
div {
color: red;
}
</style>
<div data-v-469af010="">
<ul data-v-469af010="">
<li data-v-469af010="">
<div data-v-469af010="" >
3. Binding
<template>
<div>
{{ message }}
<button v-on:click="message = 'Yay!'"></button>
</div>
</template>
<script>
export default {
data () {
return {
message: "Hello, World!"
}
}
</script>
//...
data () {
return {
message: 'Hello, World!'
}
},
//...
{__ob__: Observer}
message:(...)
▼ __ob__:Observer
▶ dep: Dep {id: 8, subs: Array(0)}
▶ value: {__ob__: Observer}
vmCount:1
__proto__: Object
▶ get message: ƒ reactiveGetter()
▶ set message:ƒ reactiveSetter(newVal)
▶ __proto__: Object
/**
* Walk through each property and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
40b -> 760b
4. Data flow
Vue.use(Vuex)
//...
let app = new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
const store = createStore(rootReducer)
//...
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
const Shawermeter = {
template: `<div>{{ score }}</div>`,
computed: {
count () {
return this.$store.state.score
}
}
}
function Shawermeter({score}) {
return <div>{ score }</div>
}
export default connect(
state => {score: state.score}
)(Shawermeter)
const store = new Vuex.Store({
state: {
reviews: [{ score: 4.3, text: '...'}, { score: 3.2, text: '...'}]
},
getters: {
topReviews: state => {
return state.reviews.filter(review => reviews.score > 4)
}
}
})
const store = new Vuex.Store({
state: { count: 1 },
mutations: {
increment (state) {
state.count++
}
}
})
//...
store.commit('increment')
actions: {
incrementAsync ({ commit }, amount) {
setTimeout(() => {
commit('increment', amount)
}, 1000)
}
}
//...
store.dispatch('incrementAsync', { amount: 10 })
function incrementAsync(amount) {
return function(dispatch) {
setTimeout(() => {
dispatch({type: 'increment', amount}), 1000)
}
}
}
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
// resolve or reject
})
}
}
//...
store.dispatch('actionA').then(() => { //...
function actionA(data) {
return function(dispatch) {
dispatch({type: 'startActionA'})
asyncFunction.then(dispatch({type: 'endActionA', data})
}
}
//...
dispatch(actionA).then(() => { //...
5. Выводы