loading...

0

vue实现流程

vue读完大概需要12分钟

  • 发布时间:2018-03-26 17:10 星期一
  • 刘伟波
  • 331
  • 更新于2018-09-12 19:55 星期三

    使用框架和jquery的区别?

                1、数据和视图的分离,解耦(开放封闭原则)

                2、以数据驱动视图,只关心数据变化,dom操作被封装

    MVVM:model(模型数据)         view(视图模板)         ViewModel(DOM listeners,Date Bingings)一种创新

    三要素:响应式、模板引擎、渲染

    

    1.diff算法是linux的基础命令,是git基本工具

    2.vdom使用diff算法是为了找出需要更新的节点

    3.diff实现,patch(container,vnode)(初次创建),patch(vnode,newVnode)(后面进行diff算法更新)

    4.核心逻辑:下面的createElement和updateChildren

  


1.vdom是什么?为何使用vdom?

        是虚拟dom,用js模拟dom结构,dom操作非常昂贵,将dom操作放在js层,提高效率

    2.vdom如何使用?核心函数是什么?

        可以用snabbdom来举例,核心函数为h函数和patch函数,vue的_c函数是借助snabdom的h函数,基本没变,返回的是Vnode节点

      

            核心三要素:

                1。响应式 Object.defineProperty

                    1)get方法的必要性,可以监听data的哪些数据被用到,没有用到不会走get,set的时候也不用关心,避免不必要的渲染

                    模拟将data代理到vm上

                2.模板   所有的信息都在   render函数-with()  (开发中不要使用,vue内部使用)

                    1)本质:字符串,有逻辑,嵌入html变量

                    2)有逻辑,如v-if,必须要用js实现,(js才是图灵完备的语言)

                    3)render最终返回的是节点 调用vm.__patch__进行对比更新dom,执行updateComponent函数,参照snnabdom的patch函数

               3.模板解析

                    render最终返回的是节点 调用vm.__patch__进行对比更新dom,执行updateComponent函数,参照snnabdom的patch函数

            VUE整个实现流程

                1.解析模板为render函数   2.响应式开始监听     3.首次渲染,显示页面,且绑定依赖      4.data属性变化,触发render

            // 以下是手写的render函数

function render () {
with (this) { //this就是vm
return _c(
'div',
{
attrs: {'id': 'app'}
},
[
_c('p', [_v(_s(price))])
]
)
}
}
function render1 () { //不用width
return vm._c(
'div',
{
attrs: {'id': 'app'}
},
[
vm._c('p', [vm._v(vm._s(price))])
]
)
}
// vm._c创建元素 vm._v创建文本节点 vm._s就是转化为字符串
with (this) { //this就是vm
return _c(
'div',
{attrs: {'id': 'app'}},
[
_c('div',
[_c('input', {
directives: [{
name: 'model',
rawName: 'v-model',
value: (title),
expression: 'title'
}],
domProps: {'value': (title)},
on: {
'input': function ($event) {
if ($event.target.composing) return
title = $event.target.value //set方法
}
}
}),
_v(' '),
_c('button',
{on: {'click': add}},
[_v('submit')])]),
_v(' '),
_c('div',
[_c('ul',
_l((list), //v-for
function (item) {
return _c('li', [_v(_s(item))])
}
)
)
]
)
]
)
}
//v-for   vm._l循环创建元素   最终返回的是节点  调用vm.__patch__进行对比更新dom,参照snnabdom的patch函数
// data 独立
var data = {
title: '',
list: []
}
// 初始化 Vue 实例
var vm = new Vue({
el: '#app',
data: data,
methods: {
add: function () {
this.list.push(this.title)
this.title = ''
}
}
})
<div id="app">
<div>
<input v-model="title">
<button v-on:click="add">submit</button>
</div>
<div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>

</div>             

   

var vm = {}
var data = {
name: 'lisi',
age: 30
}
var key;
for(key in data){
(function (key) {
Object.defineProperty(vm,key,{
get:function () {
console.log('get',data[key])
return data[key]
},
set:function (newVal) {
console.log('set',newVal)
data[key]=newVal
}
})
})(key)
}
<body>
    <div id="app">
        <input type="text" id="txt">
        <p id="show-txt"></p>
    </div>
    <script>
        var obj = {}
        Object.defineProperty(obj, 'txt', {
            get: function () {
                return obj
            },
            set: function (newValue) {
                document.getElementById('txt').value = newValue
                document.getElementById('show-txt').innerHTML = newValue
            }
        })
        document.addEventListener('keyup', function (e) {
            obj.txt = e.target.value
        })
    </script>
</body>

    createElement节点的创建

function createElement(vnode) {
var tag = vnode.tag // 'ul'
var attrs = vnode.attrs || {}
var children = vnode.children || []
if (!tag) {
return null
}

// 创建真实的 DOM 元素
var elem = document.createElement(tag)
// 属性
var attrName
for (attrName in attrs) {
if (attrs.hasOwnProperty(attrName)) {
// 给 elem 添加属性
elem.setAttribute(attrName, attrs[attrName])
}
}
// 子元素
children.forEach(function (childVnode) {
// 给 elem 添加子元素
elem.appendChild(createElement(childVnode)) // 递归
})

// 返回真实的 DOM 元素
return elem
}

updateChildren和replaceNode节点的更新和替换(暂不考虑,属性,节点的增加删除)

function updateChildren(vnode, newVnode) {
var children = vnode.children || []
var newChildren = newVnode.children || []

children.forEach(function (childVnode, index) {
var newChildVnode = newChildren[index]
if (childVnode.tag === newChildVnode.tag) {
// 深层次对比,递归
updateChildren(childVnode, newChildVnode)
} else {
// 替换
replaceNode(childVnode, newChildVnode)
}
})
}

function replaceNode(vnode, newVnode) {
var elem = vnode.elem // 真实的 DOM 节点
var newElem = createElement(newVnode)

// 替换
}


你可能感兴趣的文章

    发表评论

    评论支持markdown,评论内容不能超过500字符,如果内容过多或者要及时回复,建议去 平台,一般一天之内就会回复。
    关于技术问题或者有啥不懂的都可以留言,我会定期回复答 疑,推荐最新仓库 前端知识体系, 感謝支持!