Blog icon indicating copy to clipboard operation
Blog copied to clipboard

《深入浅出Vue.js》讨论区

Open berwin opened this issue 5 years ago • 67 comments

关于本书的任何意见和建议都可以在这里讨论~

可以在这里免费阅读本书第九章:http://www.ituring.com.cn/book/tupubarticle/25715

书中的代码:https://github.com/berwin/easy-to-understand-Vue.js-examples

也可以加入本书的微信讨论群(群已满100人,添加微信 Berwin1995 我拉进群,加我好友时建议说明自己是Vue.js读者)。

berwin avatar Feb 26 '19 08:02 berwin

书中第192页的图14-1在排版阶段给箭头弄成了双向的箭头,其实是单向的箭头~正确的原图如下

14-1

berwin avatar Mar 28 '19 02:03 berwin

书中第 40 页,单词拼写错误,splice被写成 slice了,少了个字母p。如下所示:

splice勘误

berwin avatar Apr 09 '19 07:04 berwin

书中第11页,这是不得恢复先入栈的target?

image

vue.js源码/src/core/observer/dep.js#L58-L66/src/core/observer/watcher.js#L119是通过栈来做的。如果不恢复先入栈的target,就不能实现深层次的响应了

  get () {
    const preTarget = window.target
    window.target = this
    const value = this.getter.call(this.vm, this.vm)
    window.target = preTarget
    return value
  }

cytle avatar Apr 15 '19 15:04 cytle

@cytle 对的,Vue.js的源码是一个栈。但书里并不是100%还原源码,因为真实的Vue.js有很多用于处理细节和bug的代码,这些代码并不利于初学者学习,会干扰读者理解主要思想。书里用 window.target 来实现在原理与思想上是一样的,而且理解成本更低。

举个例子:假设我们的目标是打印log,初学者只需要理解console.log能打印就行了,但真实项目代码中可能为了兼容,会写一些额外的代码来兼容 console.log 语法。但其实对于学习来说没必要关注兼容问题,他只需要理解这里的作用是打印log就行了。😁😁

berwin avatar Apr 17 '19 07:04 berwin

@cytle 对的,Vue.js的源码是一个栈。但书里并不是100%还原源码,因为真实的Vue.js有很多用于处理细节和bug的代码,这些代码并不利于初学者学习,会干扰读者理解主要思想。书里用 window.target 来实现在原理与思想上是一样的,而且理解成本更低。

举个例子:假设我们的目标是打印log,初学者只需要理解console.log能打印就行了,但真实项目代码中可能为了兼容,会写一些额外的代码来兼容 console.log 语法。但其实对于学习来说没必要关注兼容问题,他只需要理解这里的作用是打印log就行了。😁😁

嗯,我提出这个问题是看到这里时候发现和我之前理解的有冲突,这里不处理target总觉得怪怪的😁。不过你说的很有道理,能够理解

cytle avatar Apr 17 '19 09:04 cytle

求拉一下微信进vue二维码失效了, 微信号xyzxiaozhongge。@berwin

NuoHui avatar May 02 '19 08:05 NuoHui

求拉微信群 lidog000

lidog avatar May 07 '19 08:05 lidog

为什么Dep的notify函数里const sub = this.subs.slice(), 要这样多一步呢? 不直接用const sub = this.subs,这样有什么特别用意吗?

front-vb-charcarron avatar May 07 '19 14:05 front-vb-charcarron

为什么Dep的notify函数里const sub = this.subs.slice(), 要这样多一步呢? 不直接用const sub = this.subs,这样有什么特别用意吗?

表示拷贝一份subs,如果没理解错的话,是为了稳定subs列表,subs[i].update()会触发Watcher.get(),重新计算,这过程中可能会增加subs

cytle avatar May 07 '19 14:05 cytle

@cytle subs好像不会增加,因为每个属性对应一个Dep, 然后每次改变就往对应的Dep的subs塞一个watcher。但是后来我发现我更改值的次数多了,就会塞更多的watcher,然后没事通知Dep的时候就会重复触发多次watcher,这样显然不对,所以我改成this.subs.slice(this.subs.length - 1)让它每次都值通知最新的watcher。源码也是写this.subs.slice(),所以我就很疑惑。

front-vb-charcarron avatar May 07 '19 15:05 front-vb-charcarron

@cytle subs好像不会增加,因为每个属性对应一个Dep, 然后每次改变就往对应的Dep的subs塞一个watcher。但是后来我发现我更改值的次数多了,就会塞更多的watcher,然后没事通知Dep的时候就会重复触发多次watcher,这样显然不对,所以我改成this.subs.slice(this.subs.length - 1)让它每次都值通知最新的watcher。源码也是写this.subs.slice(),所以我就很疑惑。

  1. 比如计算属性,计算属性里面有if判断,有可能Dep会增加sub
  2. 因为书里的实现没有去重,vue源码先判断是否已经添加sub。https://github.com/vuejs/vue/blob/dev/src/core/observer/watcher.js#L133

cytle avatar May 07 '19 15:05 cytle

勘误~ 书中第59页,6.3.6的那个代码是错的,第三次印刷已经修复该错误。正确的代码是:

{
  functionalContext: {...},
  functionalOptions: {...},
  context: {...},
  data: {...}
  tag: "div",
  ...
}

berwin avatar May 08 '19 02:05 berwin

image 你好 请问第四章 35页提到如果watcher的expOrFn参数是一个表达式的话,肯定只收集一个Dep, 但是如果表达式是x.y.z ,当watch中调用data.x.y.z时 ,x,y,z每一个对应Object.defineProperty中get都会分别被触发,这样他们三个的dep实例不是都会被当前watch实例收集吗??这样watch不就收集了3个dep实例吗

CMS2019 avatar May 13 '19 09:05 CMS2019

@CMS2019 对哒~ 是这样的~ 你可以写个demo测一下~

berwin avatar May 13 '19 10:05 berwin

@berwin 你好 ,刚刚测了一下确实会收集 x,y,z 三个依赖到一个watch中. 谢谢😆

CMS2019 avatar May 14 '19 05:05 CMS2019

博文好,第59页的组件节点,componentOptions属性包含了tag等信息,但是下面的tag是写在和componentOptions同级的位置呀. 不是应该如下这样吗 { componentOptions:{ tag:"vue-component-1-child" } } 是我理解错了吗?

Boboboer avatar Jun 08 '19 03:06 Boboboer

@Boboboer 哈哈哈哈,这块确实有点没写清楚,因为有两个tag。例如:同级的tag叫:"vue-component-1-child",那么componentOptions里面的tag就叫“child" 😂

berwin avatar Jun 10 '19 09:06 berwin

为什么不出pdf版本啊

nibihzoay avatar Jun 24 '19 03:06 nibihzoay

@nibihzoay 这个都是出版社规定哒,我也不知道为啥没有pdf版,哈哈哈哈~

berwin avatar Jun 24 '19 03:06 berwin

@cytle 对的,Vue.js的源码是一个栈。但书里并不是100%还原源码,因为真实的Vue.js有很多用于处理细节和bug的代码,这些代码并不利于初学者学习,会干扰读者理解主要思想。书里用 window.target 来实现在原理与思想上是一样的,而且理解成本更低。

举个例子:假设我们的目标是打印log,初学者只需要理解console.log能打印就行了,但真实项目代码中可能为了兼容,会写一些额外的代码来兼容 console.log 语法。但其实对于学习来说没必要关注兼容问题,他只需要理解这里的作用是打印log就行了。😁😁

第11页的第12行对于理解造成了一些困扰:我想了一段时间为什么 let value = this.getter.call(this.vm, this.vm) 不是 let value = this.getter(this.vm)或者this.getter.call(null, this.vm).

后来明白,this.getter.call(this.vm, this.vm)中的第一个参数是为自定义getter服务的。调用this.$watch(...)时,第一个参数也可以是一个用于取值的函数,此时需要绑定this到vm(而不是Watcher)。

建议增加一些注释,或者调整一下写法。望采纳

ghost avatar Jun 25 '19 07:06 ghost

第九页中notify()的subs[i].update()是不是 watcher的update()

shakerjim avatar Jul 08 '19 03:07 shakerjim

从1.2直接跳到3.4,这是怎么回事?看的一愣一愣的。 WechatIMG8

JJoinIn avatar Jul 08 '19 14:07 JJoinIn

@JJoinIn 这是出版社装订的问题,一般是极个别现象,昨天微信上要了您的收获地址,现在已经免费给您发了一本新书在路上,注意查收噢~~

berwin avatar Jul 10 '19 04:07 berwin

书本第40页4.2.3,书本前面讲到过像this.list[0] = 2这种操作Vue是无法检测到的,那么调用observerArray()循环检测数组中的每一项时,当数组值不是Object而是Number时,调用this.walk(value)方法检测到不是Object就不会进行下一步监听,那么4.2.3例子中直接使用target[key] = val 不是不会触发视图更新?而且vm.$set(list,0,'2')这种方式按该例子看来不是等同于 this.list[0] = 2么?

XYH1996 avatar Jul 22 '19 14:07 XYH1996

@XYH1996 https://github.com/berwin/Blog/issues/41#issuecomment-513837483

berwin avatar Jul 22 '19 15:07 berwin

这阵子刚阅读完这本书,有一个小疑问,思来想去没想通。就是关于:本书第15页上说的,外界通过Watcher来读取数据,从而触发getter来收集依赖。 很好奇外界是怎么通过Watcher来读取数据的。可是又没想不通。望得到大佬的指点。

melon95 avatar Aug 28 '19 13:08 melon95

看来你漏掉了一些细节,vm. _render()时候会依次访问到依赖的所有数据,触发getter

---原始邮件--- 发件人: "shisanOnly"<[email protected]> 发送时间: 2019年8月28日(星期三) 晚上9:14 收件人: "berwin/Blog"<[email protected]>; 抄送: "Mention"<[email protected]>;"XYH1996"<[email protected]>; 主题: Re: [berwin/Blog] 《深入浅出Vue.js》讨论区 (#34)

这阵子刚阅读完这本书,有一个小疑问,思来想去没想通。就是关于:本书第15页上说的,外界通过Watcher来读取数据,从而触发getter来收集依赖。 很好奇外界是怎么通过Watcher来读取数据的。可是又没想不通。望得到大佬的指点。

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

XYH1996 avatar Aug 28 '19 13:08 XYH1996

@shisanOnly 外界有很多种途径可以通过Watcher触发getter,最常见的就是 new Watcher()的时候。在用户角度,像vm.$watch就可以让Watcher触发getter~

berwin avatar Aug 29 '19 10:08 berwin

因为Vue把细粒度调整到中级,状态变化后只会通知到组件,组件内部在使用虚拟DOM进行对比。是不是可以理解为每个Vue实例是不是都只会有一个依赖,也就是只有一个Watcher。

melon95 avatar Aug 31 '19 06:08 melon95

new Watcher()

请问 new Watcher()是在哪里执行的,我只看到了定义Watcher的地方。

melon95 avatar Aug 31 '19 07:08 melon95