[{"data":1,"prerenderedAt":100},["ShallowReactive",2],{"content:\u002Fposts\u002F2022\u002Fvue3-mini-core":3,"surround:\u002Fposts\u002F2022\u002Fvue3-mini-core":89},{"id":4,"title":5,"body":6,"canonical":68,"categories":69,"date":71,"description":72,"draft":73,"extension":74,"image":75,"meta":76,"navigation":77,"path":78,"permalink":68,"readingTime":79,"recommend":68,"references":68,"seo":84,"sitemap":85,"stem":86,"tags":87,"type":68,"updated":71,"__hash__":88},"content\u002Fposts\u002F2022\u002Fvue3-mini-core.md","Vue3 响应式系统",{"type":7,"value":8,"toc":61},"minimark",[9,14,24,28,39,43,51,55],[10,11,13],"h1",{"id":12},"vuejs","Vue.js",[15,16,17],"p",{},[18,19,23],"a",{"href":20,"rel":21},"https:\u002F\u002Fcn.vuejs.org\u002F",[22],"nofollow","官网地址(中文)",[25,26,27],"h2",{"id":27},"响应式",[29,30,36],"pre",{"className":31,"code":33,"language":34,"meta":35},[32],"language-js","let activeEffect\nclass Dep {\n    subscribers = new Set()\n\n    define() {\n        if (activeEffect) {\n            this.subscribers.add(activeEffect)\n        }\n    }\n\n    notify() {\n        this.subscribers.forEach((effect) => {\n            effect()\n        })\n    }\n}\n\nfunction watchEffect(effect) {\n    activeEffect = effect\n    effect()\n    activeEffect = null\n}\n\nconst targetMap = new WeakMap()\nfunction getDep(target, key) {\n    let depsMap = targetMap.get(target)\n    if (!depsMap) {\n        depsMap = new Map()\n        targetMap.set(target, depsMap)\n    }\n\n    let dep = depsMap.get(key)\n    if (!dep) {\n        dep = new Dep()\n        depsMap.set(key, dep)\n    }\n    return dep\n}\nconst reactiveHandlers = {\n    get(target, key, receiver) {\n        const dep = getDep(target, key)\n        dep.define()\n        return Reflect.get(target, key, receiver)\n    },\n    set(target, key, value, receiver) {\n        const dep = getDep(target, key)\n        const result = Reflect.set(target, key, value, receiver)\n        dep.notify()\n        return result\n    },\n}\nfunction reactive(raw) {\n    return new Proxy(raw, reactiveHandlers)\n}\n\n\u002F\u002F 使用\nconst state = reactive({\n    count: 0,\n})\nwatchEffect(() => {\n    console.log(state.count)\n})\nstate.count++\n","js","",[37,38,33],"code",{"__ignoreMap":35},[25,40,42],{"id":41},"虚拟-dom-渲染","虚拟 dom \u002F 渲染",[29,44,49],{"className":45,"code":47,"language":48,"meta":35},[46],"language-html","\u003Cstyle>\n  .red {\n    color: red;\n  }\n  .green {\n    color: green;\n  }\n\u003C\u002Fstyle>\n\n\u003Cdiv id=\"app\">\u003C\u002Fdiv>\n\n\u003Cscript>\n  function h(tag, props, children) {\n    return { tag, props, children }\n  }\n\n  function mount(vnode, container) {\n    const el = (vnode.el = document.createElement(vnode.tag))\n    \u002F\u002F props\n    if (vnode.props) {\n      for (const key in vnode.props) {\n        const value = vnode.props[key]\n        el.setAttribute(key, value)\n      }\n    }\n    \u002F\u002F children\n    if (vnode.children) {\n      if (typeof vnode.children === \"string\") {\n        el.textContent = vnode.children\n      } else {\n        vnode.children.forEach((child) => {\n          mount(child, el)\n        })\n      }\n    }\n    container.appendChild(el)\n  }\n\n  const vdom = h(\"div\", { id: \"hello\", class: \"red\" }, [h(\"span\", null, \"hello\")])\n\n  mount(vdom, document.getElementById(\"app\"))\n\n  function patch(n1, n2) {\n    if (n1.tag === n2.tag) {\n      const el = (n2.el = n1.el)\n      \u002F\u002F props\n      const oldProps = n1.props || {}\n      const newProps = n2.props || {}\n\n      for (const key in newProps) {\n        const oldVal = oldProps[key]\n        const newVal = newProps[key]\n        if (newVal !== oldVal) {\n          el.setAttribute(key, newVal)\n        }\n      }\n\n      for (const key in oldProps) {\n        if (!(key in newProps)) {\n          el.removeAttribute(key)\n        }\n      }\n\n      \u002F\u002F children\n      const oldChildren = n1.children\n      const newChildren = n2.children\n      if (typeof newChildren === \"string\") {\n        if (typeof oldChildren === \"string\") {\n          if (newChildren !== oldChildren) {\n            el.textContent = newChildren\n          }\n        } else {\n          el.textContent = newChildren\n        }\n      } else {\n        if (typeof oldChildren === \"string\") {\n          el.innerHTML = \"\"\n          newChildren.forEach((child) => {\n            mount(child, el)\n          })\n        } else {\n          const commonLength = Math.min(oldChildren.length, newChildren.length)\n          for (let i = 0; i \u003C commonLength; i++) {\n            patch(oldChildren[i], newChildren[i])\n          }\n          if (newChildren.length > oldChildren.length) {\n            newChildren.slice(oldChildren.length).forEach((child) => {\n              mount(child, el)\n            })\n          }\n          if (newChildren.length \u003C oldChildren.length) {\n            oldChildren.slice(newChildren.length).forEach((child) => {\n              el.removeChild(child.el)\n            })\n          }\n        }\n      }\n    } else {\n      \u002F\u002F replace\n    }\n  }\n\n  const vdom2 = h(\"div\", { id: \"hello\", class: \"green\" }, [h(\"span\", null, \"change!\")])\n  patch(vdom, vdom2)\n\u003C\u002Fscript>\n","html",[37,50,47],{"__ignoreMap":35},[25,52,54],{"id":53},"两者结合组成-mini-vue","两者结合组成 mini-Vue",[29,56,59],{"className":57,"code":58,"language":48,"meta":35},[46],"\u003Cdiv id=\"app\">\u003C\u002Fdiv>\n\n\u003Cscript>\n  function h(tag, props, children) {\n    return { tag, props, children }\n  }\n\n  function mount(vnode, container) {\n    const el = (vnode.el = document.createElement(vnode.tag))\n    \u002F\u002F props\n    if (vnode.props) {\n      for (const key in vnode.props) {\n        const value = vnode.props[key]\n        if (key.startsWith(\"on\")) {\n          el.addEventListener(key.slice(2).toLowerCase(), value)\n        } else {\n          el.setAttribute(key, value)\n        }\n      }\n    }\n    \u002F\u002F children\n    if (vnode.children) {\n      if (typeof vnode.children === \"string\") {\n        el.textContent = vnode.children\n      } else {\n        vnode.children.forEach((child) => {\n          mount(child, el)\n        })\n      }\n    }\n    container.appendChild(el)\n  }\n\n  function patch(n1, n2) {\n    if (n1.tag === n2.tag) {\n      const el = (n2.el = n1.el)\n      \u002F\u002F props\n      const oldProps = n1.props || {}\n      const newProps = n2.props || {}\n\n      for (const key in newProps) {\n        const oldVal = oldProps[key]\n        const newVal = newProps[key]\n        if (newVal !== oldVal) {\n          el.setAttribute(key, newVal)\n        }\n      }\n\n      for (const key in oldProps) {\n        if (!(key in newProps)) {\n          el.removeAttribute(key)\n        }\n      }\n\n      \u002F\u002F children\n      const oldChildren = n1.children\n      const newChildren = n2.children\n      if (typeof newChildren === \"string\") {\n        if (typeof oldChildren === \"string\") {\n          if (newChildren !== oldChildren) {\n            el.textContent = newChildren\n          }\n        } else {\n          el.textContent = newChildren\n        }\n      } else {\n        if (typeof oldChildren === \"string\") {\n          el.innerHTML = \"\"\n          newChildren.forEach((child) => {\n            mount(child, el)\n          })\n        } else {\n          const commonLength = Math.min(oldChildren.length, newChildren.length)\n          for (let i = 0; i \u003C commonLength; i++) {\n            patch(oldChildren[i], newChildren[i])\n          }\n          if (newChildren.length > oldChildren.length) {\n            newChildren.slice(oldChildren.length).forEach((child) => {\n              mount(child, el)\n            })\n          }\n          if (newChildren.length \u003C oldChildren.length) {\n            oldChildren.slice(newChildren.length).forEach((child) => {\n              el.removeChild(child.el)\n            })\n          }\n        }\n      }\n    } else {\n      \u002F\u002F replace\n    }\n  }\n\n  \u002F\u002F reactive\n  let activeEffect\n  class Dep {\n    subscribers = new Set()\n\n    depend() {\n      if (activeEffect) {\n        this.subscribers.add(activeEffect)\n      }\n    }\n\n    notify() {\n      this.subscribers.forEach((effect) => {\n        effect()\n      })\n    }\n  }\n\n  function watchEffect(effect) {\n    activeEffect = effect\n    effect()\n    activeEffect = null\n  }\n\n  const targetMap = new WeakMap()\n  function getDep(target, key) {\n    let depsMap = targetMap.get(target)\n    if (!depsMap) {\n      depsMap = new Map()\n      targetMap.set(target, depsMap)\n    }\n\n    let dep = depsMap.get(key)\n    if (!dep) {\n      dep = new Dep()\n      depsMap.set(key, dep)\n    }\n    return dep\n  }\n  const reactiveHandlers = {\n    get(target, key, receiver) {\n      const dep = getDep(target, key)\n      dep.depend()\n      return Reflect.get(target, key, receiver)\n    },\n    set(target, key, value, receiver) {\n      const dep = getDep(target, key)\n      const result = Reflect.set(target, key, value, receiver)\n      dep.notify()\n      return result\n    },\n  }\n  function reactive(raw) {\n    return new Proxy(raw, reactiveHandlers)\n  }\n\n  const App = {\n    data: reactive({\n      count: 22,\n    }),\n    render() {\n      return h(\n        \"div\",\n        {\n          onClick: () => {\n            this.data.count++\n          },\n        },\n        String(this.data.count)\n      )\n    },\n  }\n  function mountApp(component, container) {\n    let isMounted = false\n    let prevVdom\n    watchEffect(() => {\n      if (!isMounted) {\n        prevVdom = component.render()\n        mount(prevVdom, container)\n        isMounted = true\n      } else {\n        const newVdom = component.render()\n        patch(prevVdom, newVdom)\n        prevVdom = newVdom\n      }\n    })\n  }\n  mountApp(App, document.getElementById(\"app\"))\n\u003C\u002Fscript>\n",[37,60,58],{"__ignoreMap":35},{"title":35,"searchDepth":62,"depth":62,"links":63},4,[64,66,67],{"id":27,"depth":65,"text":27},2,{"id":41,"depth":65,"text":42},{"id":53,"depth":65,"text":54},null,[70],"代码","2022-12-04 15:43:03","跟着尤大实现一下 vue3 的响应式系统",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002F679ad72e4f05d-78.webp",{},true,"\u002Fposts\u002F2022\u002Fvue3-mini-core",{"text":80,"minutes":81,"time":82,"words":83},"5 min read",4.52,271200,904,{"title":5,"description":72},{"loc":78},"posts\u002F2022\u002Fvue3-mini-core",[],"Vwfkauz88BLZu7mPmKlSQGk_01NDGB2o4yEF9ck860I",[90,95],{"title":91,"path":92,"stem":93,"date":94,"type":68,"children":-1},"pinia 快速使用","\u002Fposts\u002F2022\u002Fpinia-setup","posts\u002F2022\u002Fpinia-setup","2022-12-04 15:42:19",{"title":96,"path":97,"stem":98,"date":99,"type":68,"children":-1},"oss搭建个人图床","\u002Fposts\u002F2022\u002Foss-builds-a-personal-image-bed","posts\u002F2022\u002Foss-builds-a-personal-image-bed","2022-12-04 15:44:28",1789642596561]