#code-for-vue3-book
code-for-vue-3-book's Introduction
code-for-vue-3-book's People
Forkers
yill625 godguns kongmoumou maicfir konglingwen94 leehave nbili tosn heart-er krislee94 runningdoubi xiaosili hongbusi zy0228 younglina yisenfe goldbeener ceidion majunchang zhuijing lhxlotus walkalone0325 qiang520184 bingyuan1030 ghostchan xiashui1994 cherishtheyouth okxiaoliang4 yaob1990 dot1q84 fubaooo muluoguiben sunnyxujian smartzheng cgb-frontend liyincode chenyang3411 qinglingzhiyu yuccie clyan zxfjd3g sepush uuuvvv this-spring alexvagrant zhengxhui caixingorg donmind29 esdiarap variy xz9688 hsqcoollaughing enjoy-li kusou1 arabeseque vaebe zer0fire wlllyfor simon-he95 l1150143576 que-yue yangtian-yu jayyuz chia-l long-smart airhua-byte deerloves xuxiaobo520 sunorry fancn21th linguanfuyo winwinwinw geographerwang recoluan orientmoon 122036482 yuqingzhijie jeffrey-mu kakachake daleqq zhengsansan super-britz alicecooper214 husilu lwm98 haigeno1 shaun931026 eplayed wsypower griseoldman easyforever jinding123 henry-diasa timzhang2090 shguanbin lxw-peter superstrongz chenchunchang nico1988 yaolinhongcode-for-vue-3-book's Issues
【60页】避免无限递归循环 的处理逻辑有遗漏
【429 页】文字错误
429 页,第一行,“图 16-8” 修改为 “图 16-16”
47页,代码,get访问器,在activeEffect不存在的情况下,不应该直接返回 return,而是应该返回 targte[key]。
get(target, key) {
// 没有副作用函数产生
if (!activeEffect) return target[key];
// ......
return target[key];
}
【221页】代码错误
221页示例代码第15行
patch(oldChildren[i], newChildren[i])
应改为
patch(oldChildren[i], newChildren[i], container)
否则oldChildren 中如果有 Fragment
会出错。
【261 页】代码有误
while (...) {
if (!oldStartVNode) {
oldStartVNode = oldChildren[++oldStartIdx]
} else if (!oldEndVNode) {
oldEndVNode = newChildren[--oldEndIdx]
}
...
}
第五行应该为 oldEndVNode = oldChildren[--oldEndIdx]
【213页】错别字
213页 倒数第二段最后一行 “我们就可以用它来描述Itmes.vue组件的模板了”
Itmes => Items
【372页】示例代码 57 行,`currentStat` 拼写错误
代码是正确的,书上不对
第4章: 4.3 , 47 页的示例, activeEffect 哪里设置的
【126页】代码注释错别字
【126页】代码注释错别字
第二段代码,11行注释,应该是“避免重复创建”,而不是“帮忙”
【21页】代码缩进不一致
[107、108页] 示例代码 new Proxy 中应该是 obj,而不是 objm
function reactive(obj) {
return new Proxy(obj, {
// ...
})
}
【48页】图4-3, WeakMap的key 最后应该是target-n
272 文字有误
【174页】新vnode的值为null,即什么都(不)渲染
【80页】示例代码 26 行,入参顺序错误
根据书上之前的示例代码,watch中回调的入参顺序应为 cb(newValue, oldValue, onInvalidate)
【241 页】文字错误
【303页】代码错误
303页 第一段代码 20 行,jon 改为 job
【57 页】`data.foo` 应为 `obj.foo`
在这种情况下,我们希望当修改 data.foo 时会触发 effectFn1 执行
应该是,“在这种情况下,我们希望当修改 obj.foo 时会触发 effectFn1 执行”
【272页】内容有误
末尾一段:
……以及相同的后置节点 p-3和 p-4……
此处应为 p-2 和 p-3
[Bug] 第 2 章 - 2.6 错误处理 - callWithErrorHandling(page23)
当用户不去注册错误处理程序 utils.registerErrorHandler((e) => {})
,handleError 为 null,执行报错 handleError is not a function
;
let handleError = null
export default {
foo(fn) {
callWithErrorHandling(fn)
},
bar(fn) {
callWithErrorHandling(fn)
},
registerErrorHandler(fn) {
handleError = fn
}
}
function callWithErrorHandling(fn) {
try {
fn && fn()
} catch (e) {
handleError(e)
}
}
function callWithErrorHandling(fn) {
try {
fn && fn()
} catch (e) {
handleError && handleError(e)
}
}
【119页】arr[100] = bar,bar缺少双引号
书上:
- 添加新元素:
arr[100] = bar
修改为:
- 添加新元素:
arr[100] = 'bar'
【58页】嵌套的 effect 与 effect 栈 的处理逻辑有遗漏
【74页】watch 的实现原理 建议增加读者注意
目前书中所实现的代码,只能在监听有返回的 getter 函数时,才能将 newValue,oldValue 正确传入,其他情况都是 undefined。
有返回的函数是指:
// 1. 简写箭头函数
() => obj.foo; // 收集 obj.foo 的值为 newValue, oldValue
// 2. 完整写法
() => {return obj.foo};
// 3. 监听多个 getter
// 收集 obj.bar 的值为 newValue, oldValue;如果没有返回值,则 newValue 和 oldValue 都是 undefined
() => {obj.foo; return obj.bar};
测试示例图:
原因分析:
代码中 newValue
和 oldValue
都是通过 effectFn()
的执行结果赋值的。而 effectFn()
的执行结果又依赖于 副作用函数
的执行结果。在当前上下文中 getter()
的返回值决定了 newValue,oldValue 的值
【387页】语病
第二行,“把回调函数存储到 context.nodeTransforms” 改为 “把回调函数存储到 transforms”
【178】代码错误
178页 第三段代码中 第8行
el.text 应该是 el.textContent
【377 页】图片缺少箭头
377 页,图 15-12 AST 一列缺少关联箭头(Root 与 Element(div) 之间)
【111页】正文第2行
我们还修改了 get 拦截函数和 deleteProperty 拦截函数;
期望
我们还修改了 set
拦截函数和 deleteProperty 拦截函数;
[109页] 实例代码16行,代码顺序错误
const res = Reflect.get(target, key, receiver);
if (isShallow) {
return res;
}
track(target, key); // 这一行应该放在isshlallow 判断之前,否则如果是浅响应就无法收集依赖了
【67页-69页】计算属性 computed 与 lazy 思维有点跳
【67页】无缓存的 computed 实现,当 obj.foo
和 obj.bar
值变更时都会执行副作用函数,这个执行没有任何意义,因为执行后的结果并不会被收集。
- 处理方案:添加调度器,在调度器中不做任何处理。
const effectFn = effect(getter, {
lazy: true,
scheduler() {}
})
【69页】增加调度器的配置,这里调度器是 ”空参“,看书时比较困扰为什么要用 “空参”。
- 建议对空参进行说明。或者就是先解决上面提到的问题自然就引出了空参调度器的配置。
【302】【303】代码错误
- 302页 第一段代码第 9 行, ctx 改为 state
- 303页 第二段代码第 8 行同上
【77页】立即执行的 watch 与回调执行时机 代码调整建议
建议将 flush is post
时的原始代码:
scheduler: () => {
// 在调度函数中判断 flush 是否为 'post',如果是,将期放到微任务队列中执行
if (options.flush === "post") {
const p = Promise.resolve();
p.then(job);
} else {
job();
}
},
变更为:
scheduler: () => {
// 在调度函数中判断 flush 是否为 'post',如果是,将期放到微任务队列中执行
if (options.flush === "post") {
jobQueue.add(job);
flushJob();
} else {
job();
}
},
原始代码的运行结果,容易使读者产生困惑,并且新代码因为采用微任务队列,所以只会执行一次。
运行对比图:
【86页】代码有误
【303页】代码错误
303页第一段代码块,24行 清空Set:
queue.length = 0
应该改为:
queue.clear()
【380页】图15-18、15-19、15-20中缺少箭头指示。
【109-110页】示例代码,浅响应没有调用track收集响应依赖
浅响应不会执行 track
函数收集依赖,因此 target
本身的属性也不是响应式的
track
函数执行时机应在 if (isShallow) { ... }
判断语句之前
书上:
// 封装 createReactive 函数,接收一个参数 isShallow,代表是否为浅响应,默认为 false,即非浅响应
function createReactive(obj, isShallow = false) {
return new Proxy(obj, {
// 拦截读取操作
get(target, key, receiver) {
// 代理对象可以通过 raw 属性访问原始数据
if (key === 'raw') {
return target
}
const res = Reflect.get(target, key, receiver)
// 如果是浅响应,则直接返回原始值
if (isShallow) {
return res
}
track(target, key)
if (typeof res === 'object' && res !== null) {
return reactive(res)
}
return res
}
// 省略其他拦截函数
})
}
调整了下 track(target, key)
位置
修改后:
// 封装 createReactive 函数,接收一个参数 isShallow,代表是否为浅响应,默认为 false,即非浅响应
function createReactive(obj, isShallow = false) {
return new Proxy(obj, {
// 拦截读取操作
get(target, key, receiver) {
// 代理对象可以通过 raw 属性访问原始数据
if (key === 'raw') {
return target
}
track(target, key)
const res = Reflect.get(target, key, receiver)
// 如果是浅响应,则直接返回原始值
if (isShallow) {
return res
}
if (typeof res === 'object' && res !== null) {
return reactive(res)
}
return res
}
// 省略其他拦截函数
})
}
【204页】文字错误
56页组件嵌套使用 effect 函数表示,应该将 Foo.render() 给去掉
4.3章 第47页 修改 get/set 拦截器代码,set未返回true导致报错
【232】代码注释
代码中的注释”新的虚拟节点“有的使用"newVnode"有的使用"newVNode"
【137页】注释错误
新137 页,第一段代码,第 7 行注释,由 “删除。。。” 改为 "添加。。。"
【371页】示例代码中 `tokenize` 单词拼写错误
代码中是对的,但书上不正确。书上是 tokenzie
【198页】事件的处理逻辑有遗漏
if (/^on/.test(key)) {
const invokers = el._vei || (el._vei = {})
let invoker = invokers[key]
const name = key.slice(2).toLowerCase()
if (nextValue) {
if (!invoker) {
invoker = el._vei[key] = (e) => {
if (Array.isArray(invoker.value)) {
invoker.value.forEach(fn => fn(e))
} else {
invoker.value(e)
}
}
invoker.value = nextValue
el.addEventListener(name, invoker)
} else {
invoker.value = nextValue
}
} else if (invoker) {
el.removeEventListener(name, invoker)
// 移除绑定的同时需要置空或删除 el._vei
}
}
如上面代码注释出所述,如果新的绑定事件不存在,且之前绑定的invoker 存在,则移除绑定。但是移除绑定后invoker 依旧存在,所以下次再添加新的绑定事件时,只会触发invoker.value = newValue
,而不会执行addEventListener(name, invoker)
。因此,在这边需要同时置空或删除 el._vei,如el._vei = null
。
如下面例子所示:
const vnode = {
type: 'p',
props: {
onClick: () => {
alert('clicked 1')
}
},
children: 'text'
}
renderer.render(vnode, document.querySelector('#app'))
const newVnode = {
type: 'p',
props: {},
children: 'text'
}
renderer.render(newVnode, document.querySelector('#app'));
renderer.render(vnode, document.querySelector('#app'));
点击p 标签不会触发click 事件,不符合预期。
同样的问题在事件的处理章节后续的代码示例中同样存在。
【380 页】【381 页】图片错误
图 15-17、15-18、15-19、15-20, 右下 Element(p) 缺少向下箭头
【259页】图 10-19 错误
该图的 newStartIdx 应该指向 p-4。
因为前文说的是 “经过上述两个步骤后”,此时队头指针已经移动了。所以应该修改
【70页】手动调用track追踪和手动调用trigger触发,不在effect嵌套里读取value时,会爆栈
【44页】语句不通顺
【313页】代码错误
313 页,第 33 行, setupContext 改为 setupResult
closed
【96页】最底部示例代码 setter 缺少 receiver 入参
line 03 缺少 receiver 入参
书中:
set(target, key, newVal) {
// 设置属性值
const res = Reflect.set(target, key, newVal, receiver)
// ...
}
应修改为:
set(target, key, newVal, receiver) {
// 设置属性值
const res = Reflect.set(target, key, newVal, receiver)
// ...
}
【81页】正文第7行 末端 expored -> expired
正文第7行 末端 expored -> expired
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.