From 2b0d77fa700cb36468013a73759d9f6a9a91a8d5 Mon Sep 17 00:00:00 2001 From: w2xi <43wangxi@gmail.com> Date: Fri, 26 Jan 2024 13:16:52 +0800 Subject: [PATCH] feat: support render function options --- demo/22-manually-mount.html | 2 +- demo/23-counter.html | 2 +- demo/24-render-function-options.html | 51 ++++++++++++++++ demo/static/mini-vue.umd.js | 89 +++++++++++++++------------- slides.md | 30 +++++++++- 5 files changed, 130 insertions(+), 44 deletions(-) create mode 100644 demo/24-render-function-options.html diff --git a/demo/22-manually-mount.html b/demo/22-manually-mount.html index bd807dd..246bf52 100644 --- a/demo/22-manually-mount.html +++ b/demo/22-manually-mount.html @@ -50,7 +50,7 @@ } const vnode = render() -console.log(vnode); +console.log('VNode: ', vnode); mount(vnode, document.body) // vnode diff --git a/demo/23-counter.html b/demo/23-counter.html index b1264e1..f86482f 100644 --- a/demo/23-counter.html +++ b/demo/23-counter.html @@ -3,7 +3,7 @@ - Document + A counter + + +
+ + + \ No newline at end of file diff --git a/demo/static/mini-vue.umd.js b/demo/static/mini-vue.umd.js index 8b7cb3c..85d0749 100644 --- a/demo/static/mini-vue.umd.js +++ b/demo/static/mini-vue.umd.js @@ -5,50 +5,54 @@ })(this, (function (exports) { 'use strict'; function isObject(val) { - return val && typeof val === 'object' - } - - const hasOwnProperty = Object.prototype.hasOwnProperty; - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key) - } + return val && typeof val === 'object' + } - // 递归遍历 obj - function traverse(obj, seen = new Set()) { - // 避免循环引用 - if (seen.has(obj)) return - seen.add(obj); - for (let key in obj) { - if (isObject(obj[key])) { - traverse(obj[key]); - } else { - obj[key]; - } + const hasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwn(obj, key) { + return hasOwnProperty.call(obj, key) + } + + // 递归遍历 obj + function traverse(obj, seen = new Set()) { + // 避免循环引用 + if (seen.has(obj)) return + seen.add(obj); + for (let key in obj) { + if (isObject(obj[key])) { + traverse(obj[key]); + } else { + obj[key]; } - return obj - } - - function isSet(val) { - return type(val, 'set') - } - - function isMap(val) { - return type(val, 'map') } + return obj + } - function isString(val) { - return type(val, 'string') - } - - const toString = Object.prototype.toString; - function type(val, type) { - const str = toString.call(val); - const matched = str.match(/\[object (\w+)\]/); - if (matched) { - return matched[1].toLowerCase() === type.toLowerCase() - } - return false + function isSet(val) { + return type(val, 'set') + } + + function isMap(val) { + return type(val, 'map') + } + + function isString(val) { + return type(val, 'string') + } + + function isFunction(val) { + return type(val, 'function') + } + + const toString = Object.prototype.toString; + function type(val, type) { + const str = toString.call(val); + const matched = str.match(/\[object (\w+)\]/); + if (matched) { + return matched[1].toLowerCase() === type.toLowerCase() } + return false + } const reactiveMap = new Map(); function reactive(obj) { @@ -1430,7 +1434,12 @@ container = document.querySelector(container); } const template = container.innerHTML; - const render = compileToFunction(template); + let render; + if (isFunction(options.render)) { // 用户自定义渲染函数 + render = options.render; + } else { + render = compileToFunction(template); + } const setupFn = options.setup || noop; const data = proxyRefs(setupFn()); diff --git a/slides.md b/slides.md index 03dc977..70466f5 100644 --- a/slides.md +++ b/slides.md @@ -2265,7 +2265,7 @@ function mount(vnode, container) { // demo: 22-manually-mount.html const vnode = render() -console.log(vnode); +console.log('VNode: ', vnode); mount(vnode, document.body) ``` @@ -2322,7 +2322,7 @@ function createApp(options = {}) { --- -## Counter 计数器 demo +## Counter 计数器 demo: `22-counter.html` @@ -2362,6 +2362,32 @@ createApp({ +--- + +## 手写 render 函数 + +我们知道,在 Vue.js 中,可以手写 `render` 渲染函数,接下里我们也来支持下。 + +```js +// demo: 24-render-function-options.html + +function createApp(options = {}) { + const app = { + mount(container) { + // ... + let render + if (isFunction(options.render)) { // 传入 render 函数 + render = options.render + } else { + render = compileToFunction(template) + } + // ... + } + } + return app +} +``` + --- layout: image image: /mikoto-misaka.jpg