V2EX answershuto
 answershuto 最近的时间轴更新
answershuto

answershuto

  前端开发
V2EX 第 221230 号会员,加入于 2017-03-15 21:51:52 +08:00
聊聊 keep-alive 组件的使用及其实现原理
前端开发    answershuto    2017-11-13 10:14:52 AM    最后回复来自 pabupa
1
Vuex 源码解析
前端开发    answershuto    2017-11-01 15:54:24 PM    最后回复来自 geek123
7
Vue.js 源码事件机制
前端开发    answershuto    2017-09-28 00:30:16 AM    最后回复来自 Lisp
3
从 Vue.js 源码看异步更新 DOM 策略及 nextTick
  •  1   
    Vue.js    answershuto    2017-09-24 23:40:39 PM    最后回复来自 SilentDepth
    1
    VirtualDOM 与 diff(Vue 实现)
    前端开发    answershuto    2017-09-18 20:57:12 PM    最后回复来自 answershuto
    1
    说说 VNode 节点(Vue.js 实现)
    Javascript    answershuto    2017-09-11 10:49:50 AM    最后回复来自 66beta
    7
    从 Vue.js 源码角度再看数据绑定
  •  2   
    前端开发    answershuto    2017-09-05 10:00:33 AM    最后回复来自 codermagefox
    1
    一款可视化编辑手机 H5 页面的单页应用 WebApp
    分享创造    answershuto    2017-08-30 18:11:45 PM    最后回复来自 answershuto
    7
    answershuto 最近回复了
    2017-10-30 11:17:59 +08:00
    回复了 answershuto 创建的主题 前端开发 Vuex 源码解析
    @smallpath 不错~其实主要就是抽离核心的 Store 操作,以及最关键用 Vue 对象来实现数据的“响应式化”。
    2017-10-30 11:02:53 +08:00
    回复了 answershuto 创建的主题 前端开发 Vuex 源码解析
    @SourceMan ,我下次注意~
    2017-10-30 08:17:26 +08:00
    回复了 answershuto 创建的主题 前端开发 Vuex 源码解析
    ### unregisterModule

    ```Javascript
    /* 注销一个动态 module */
    unregisterModule (path) {
    /* 转化称 Array */
    if (typeof path === 'string') path = [path]

    if (process.env.NODE_ENV !== 'production') {
    assert(Array.isArray(path), `module path must be a string or an Array.`)
    }

    /*注销*/
    this._modules.unregister(path)
    this._withCommit(() => {
    /* 获取父级的 state */
    const parentState = getNestedState(this.state, path.slice(0, -1))
    /* 从父级中删除 */
    Vue.delete(parentState, path[path.length - 1])
    })
    /* 重制 store */
    resetStore(this)
    }
    ```

    同样,与 registerModule 对应的方法 unregisterModule,动态注销模块。实现方法是先从 state 中删除模块,然后用 resetStore 来重制 store。

    ### resetStore

    ```Javascript
    /* 重制 store */
    function resetStore (store, hot) {
    store._actiOns= Object.create(null)
    store._mutatiOns= Object.create(null)
    store._wrappedGetters = Object.create(null)
    store._modulesNamespaceMap = Object.create(null)
    const state = store.state
    // init all modules
    installModule(store, state, [], store._modules.root, true)
    // reset vm
    resetStoreVM(store, state, hot)
    }
    ```

    这里的 resetStore 其实也就是将 store 中的_actions 等进行初始化以后,重新执行 installModule 与 resetStoreVM 来初始化 module 以及用 Vue 特性使其“响应式化”,这跟构造函数中的是一致的。


    ## 插件

    Vue 提供了一个非常好用的插件[Vue.js devtools]( https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)

    ```Javascript
    /* 从 window 对象的__VUE_DEVTOOLS_GLOBAL_HOOK__中获取 devtool 插件 */
    const devtoolHook =
    typeof window !== 'undefined' &&
    window.__VUE_DEVTOOLS_GLOBAL_HOOK__

    export default function devtoolPlugin (store) {
    if (!devtoolHook) return

    /* devtoll 插件实例存储在 store 的_devtoolHook 上 */
    store._devtoolHook = devtoolHook

    /* 出发 vuex 的初始化事件,并将 store 的引用地址传给 deltool 插件,使插件获取 store 的实例 */
    devtoolHook.emit('vuex:init', store)

    /* 监听 travel-to-state 事件 */
    devtoolHook.on('vuex:travel-to-state', targetState => {
    /* 重制 state */
    store.replaceState(targetState)
    })

    /* 订阅 store 的变化 */
    store.subscribe((mutation, state) => {
    devtoolHook.emit('vuex:mutation', mutation, state)
    })
    }
    ```

    如果已经安装了该插件,则会在 windows 对象上暴露一个__VUE_DEVTOOLS_GLOBAL_HOOK__。devtoolHook 用在初始化的时候会触发“ vuex:init ”事件通知插件,然后通过 on 方法监听“ vuex:travel-to-state ”事件来重置 state。最后通过 Store 的 subscribe 方法来添加一个订阅者,在触发 commit 方法修改 mutation 数据以后,该订阅者会被通知,从而触发“ vuex:mutation ”事件。

    ## 最后

    Vuex 是一个非常优秀的库,代码量不多且结构清晰,非常适合研究学习其内部实现。最近的一系列源码阅读也使我自己受益匪浅,写这篇文章也希望可以帮助到更多想要学习探索 Vuex 内部实现原理的同学。
    2017-09-18 20:57:12 +08:00
    回复了 aswershuto 创建的主题 前端开发 VirtualDOM 与 diff(Vue 实现)
    由于平台字数限制放不下了,接上文。

    ## DOM 操作

    由于 Vue 使用了虚拟 DOM,所以虚拟 DOM 可以在任何支持 Javascript 语言的平台上操作,譬如说目前 Vue 支持的浏览器平台或是 weex,在虚拟 DOM 的实现上是一致的。那么最后虚拟 DOM 如何映射到真实的 DOM 节点上呢?

    Vue 为平台做了一层适配层,浏览器平台见[/platforms/web/runtime/node-ops.js]( https://github.com/answershuto/learnVue/blob/master/vue-src/platforms/web/runtime/node-ops.js)以及 weex 平台见[/platforms/weex/runtime/node-ops.js]( https://github.com/answershuto/learnVue/blob/master/vue-src/platforms/weex/runtime/node-ops.js)。不同平台之间通过适配层对外提供相同的接口,虚拟 DOM 进行操作真实 DOM 节点的时候,只需要调用这些适配层的接口即可,而内部实现则不需要关心,它会根据平台的改变而改变。

    现在又出现了一个问题,我们只是将虚拟 DOM 映射成了真实的 DOM。那如何给这些 DOM 加入 attr、class、style 等 DOM 属性呢?

    这要依赖于虚拟 DOM 的生命钩子。虚拟 DOM 提供了如下的钩子函数,分别在不同的时期会进行调用。

    ```Javascript
    const hooks = ['create', 'activate', 'update', 'remove', 'destroy']

    /*构建 cbs 回调函数,web 平台上见 /platforms/web/runtime/modules*/
    for (i = 0; i < hooks.length; ++i) {
    cbs[hooks[i]] = []
    for (j = 0; j < modules.length; ++j) {
    if (isDef(modules[j][hooks[i]])) {
    cbs[hooks[i]].push(modules[j][hooks[i]])
    }
    }
    }
    ```

    同理,也会根据不同平台有自己不同的实现,我们这里以 Web 平台为例。Web 平台的钩子函数见[/platforms/web/runtime/modules]( https://github.com/answershuto/learnVue/tree/master/vue-src/platforms/web/runtime/modules)。里面有对 attr、class、props、events、style 以及 transition (过渡状态)的 DOM 属性进行操作。

    以 attr 为例,代码很简单。

    ```Javascript
    /* @flow */

    import { isIE9 } from 'core/util/env'

    import {
    extend,
    isDef,
    isUndef
    } from 'shared/util'

    import {
    isXlink,
    xlinkNS,
    getXlinkProp,
    isBooleanAttr,
    isEnumeratedAttr,
    isFalsyAttrValue
    } from 'web/util/index'

    /*更新 attr*/
    function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
    /*如果旧的以及新的 VNode 节点均没有 attr 属性,则直接返回*/
    if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
    return
    }
    let key, cur, old
    /*VNode 节点对应的 Dom 实例*/
    const elm = vnode.elm
    /*旧 VNode 节点的 attr*/
    const oldAttrs = oldVnode.data.attrs || {}
    /*新 VNode 节点的 attr*/
    let attrs: any = vnode.data.attrs || {}
    // clone observed objects, as the user probably wants to mutate it
    /*如果新的 VNode 的 attr 已经有__ob__(代表已经被 Observe 处理过了), 进行深拷贝*/
    if (isDef(attrs.__ob__)) {
    attrs = vnode.data.attrs = extend({}, attrs)
    }

    /*遍历 attr,不一致则替换*/
    for (key in attrs) {
    cur = attrs[key]
    old = oldAttrs[key]
    if (old !== cur) {
    setAttr(elm, key, cur)
    }
    }
    // #4391: in IE9, setting type can reset value for input[type=radio]
    /* istanbul ignore if */
    if (isIE9 && attrs.value !== oldAttrs.value) {
    setAttr(elm, 'value', attrs.value)
    }
    for (key in oldAttrs) {
    if (isUndef(attrs[key])) {
    if (isXlink(key)) {
    elm.removeAttributeNS(xlinkNS, getXlinkProp(key))
    } else if (!isEnumeratedAttr(key)) {
    elm.removeAttribute(key)
    }
    }
    }
    }

    /*设置 attr*/
    function setAttr (el: Element, key: string, value: any) {
    if (isBooleanAttr(key)) {
    // set attribute for blank value
    // e.g. <option disabled>Select one</option>
    if (isFalsyAttrValue(value)) {
    el.removeAttribute(key)
    } else {
    el.setAttribute(key, key)
    }
    } else if (isEnumeratedAttr(key)) {
    el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
    } else if (isXlink(key)) {
    if (isFalsyAttrValue(value)) {
    el.removeAttributeNS(xlinkNS, getXlinkProp(key))
    } else {
    el.setAttributeNS(xlinkNS, key, value)
    }
    } else {
    if (isFalsyAttrValue(value)) {
    el.removeAttribute(key)
    } else {
    el.setAttribute(key, value)
    }
    }
    }

    export default {
    create: updateAttrs,
    update: updateAttrs
    }

    ```

    attr 只需要在 create 以及 update 钩子被调用时更新 DOM 的 attr 属性即可。
    2017-09-11 10:25:49 +08:00
    回复了 answershuto 创建的主题 Javascript 说说 VNode 节点(Vue.js 实现)
    @dcoder 3q
    2017-09-11 10:25:30 +08:00
    回复了 answershuto 创建的主题 Javascript 说说 VNode 节点(Vue.js 实现)
    @sansansan333 时间花下去了,总会有收获的哈~
    2017-09-11 10:25:03 +08:00
    回复了 answershuto 创建的主题 Javascript 说说 VNode 节点(Vue.js 实现)
    @codermagefox 哈哈谢谢
    2017-08-30 18:11:45 +08:00
    回复了 answershuto 创建的主题 分享创造 一款可视化编辑手机 H5 页面的单页应用 WebApp
    @biuuu 不带解释以为是骂人的。。。
    2017-08-30 12:23:37 +08:00
    回复了 answershuto 创建的主题 分享创造 一款可视化编辑手机 H5 页面的单页应用 WebApp
    @lqzhgood 作为技术可能多多少少对这些名称不是很喜欢,但是我似乎找不到别的更合适且让人熟悉的名词去描述 H5 这个东西了。
    2017-08-30 09:03:31 +08:00
    回复了 answershuto 创建的主题 分享创造 一款可视化编辑手机 H5 页面的单页应用 WebApp
    @v1024 H5 按照我的理解是现在常用于微信里做营销用的类似 ppt 的 HTML5 页面的称呼,所以我没用 HTML5 而用了 H5,因为这个项目就是为了产出 H5 的页面的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     936 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 19:40 PVG 03:40 LAX 12:40 JFK 15:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86