Giter Club home page Giter Club logo

vue-design's Introduction

关注公众号阅读更多文章:

HcySunYang

vue-design's People

Contributors

a20185 avatar aha2mao avatar allenfantasy avatar blacktail avatar btea avatar camoth avatar codediy avatar coderew avatar everywill avatar frankyeyq avatar hcysunyang avatar jiangxiaoxin avatar kilohaty avatar knownothingsnow avatar limengke123 avatar liximomo avatar liyangworld avatar lz-lee avatar miaoyuxinbaby avatar mingmingwon avatar nomadcheng avatar paradeto avatar peterchen1997 avatar ts0307 avatar waihoyu avatar wuyaoxing avatar xiaoyual666 avatar yaodingyd avatar yawenina avatar zhang-xiao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-design's Issues

defineReactive闭包中的dep和childOb中的dep一定得是两个不同的对象吗?

文中提到:“也就是说 childOb.dep.depend() 这句话的执行说明除了要将依赖收集到属性 a 自己的“筐”里之外,还要将同样的依赖收集到 data.a.ob.dep 这里”筐“里,为什么要将同样的依赖分别收集到这两个不同的”筐“里呢?其实答案就在于这两个”筐“里收集的依赖的触发时机是不同的,即作用不同”。

即使两个“筐”收集的依赖的触发时机不同,但是把它们俩“合二为一”,会有什么问题呢?比如:

export function defineReactive (...) {
const dep = new Dep();

// 省略

// 将闭包中的dep作为参数传给observe,并赋值给childOb的dep属性
let childOb = !shallow && observe(val, dep)

}

这样一来,依旧可以在set函数中触发闭包的dep,也可以在$set中主动触发childOb.dep。

响应式那章-数组的特殊性

一个是属于 arr 属性自身的 dep 对象,另一个是 childOb.dep 对象,其中 childOb 就是 ob1

这里其中childOb应该是ob2

关于makeMap这部分代码的实现

export function makeMap (
str: string,
expectsLowerCase?: boolean
): (key: string) => true | void {
const map = Object.create(null)
const list: Array = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
测试一下
export const isVowel = makeMap('a,e,i,o,u', true)

isVowel('e')
疑问在这???
//文中说这里返回 true,实际上返回的是一个 function. val => map[val.toLowerCase()] 或者 val => map[val]

3vue-example.md中 错误纠正

在 3vue-example.md文档中,
..............................................................................................................................
const vm: Component = this
// a uid
vm._uid = uid++
首先声明了变量 vm,其值为 this 也就是当前这个 Vue 实例啦,.........
..............................................................................................................................

vm 应该常量吧?

nextTick 实现中 microtask 先于 macrotask 执行 的描述

原文 中有以下描述:

当调用栈空闲后每次事件循环只会从 (macro)task 中读取一个任务并执行,而在同一次事件循环内会将 microtask 队列中所有的任务全部执行完毕,且要先于 (macro)task。

我的疑问在于为什么在当前 event loopmictotask queue 中的任务为什么会先于 (marco)task 执行?

根据 Tasks, microtasks, queues and schedules 中的介绍 Microtasks 中的第二段最后一句话:

microtasks always happen before the next task.

根据 W3CWHATWG living standard 所描述的 event loops processing model 中,每次 event loopstask queue 不为空的情况下始终以一个 (marco)task 作为 event loop 开始,之后才是 microtask

个人仍然觉得 @lz-lee#130 所言的当前 event loop 中的 microtask 先于 下一次 (macro)task任务执行更加合理。

并且全局执行上下文 script 作为包含初始代码执行环境的执行上下文,也并不影响 (marco)task 在当次 event loop 先于 microtask 执行的规则。那么当前 event loop 中的 microtask 先于 下一次 macrotask 更加合理?

还是我理解有误?想请教一下你们是如何理解在当前 event loopmicrotask 先于 marcotask 执行的? 能否提供一下相关的示例规范依据呢?@HcySunYang @lz-lee

关于flushCallbacks内的执行顺序

既然flushSchedulerQueue和$nextTick中的函数都是通过nextTick添加到callbacks中的,那是如何保证先执行flushSchedulerQueue的呢?比如我先执行this.$nextTick(() => console.log(1)),再执行this.a = 1,此时按理说() => console.log(1)比flushSchedulerQueue先push到callbacks中啊。请大神赐教。

生命周期钩子选项的合并策略 中的一个问题

关于mergeHook这个函数我有一个问题,您这里有一句

如果有 parentVal 那么其一定是数组,如果没有 parentVal 那么 strats[hooks] 函数根本不会执行。

我想问的是为什么没有parentVal ,strats[hooks] 函数就不会执行?在Vue 选项的合并的这段代码中

`const options = {}

let key
for (key in parent) {
mergeField(key)
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key)
}
}
function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options`

第一个for中parent中没有那个key,但在child中不是也执行了mergeField了吗?那为什么说strats[hooks]根本不会执行呢?

官方文档中的关于extends和mixins的区别解释。

官方文档对于extends的解释:允许声明扩展另一个组件(可以是一个简单的选项对象或构造函数),而无需使用 Vue.extend。这主要是为了便于扩展单文件组件。这和 mixins 类似,区别在于,组件自身的选项会比要扩展的源组件具有更高的优先级。
不理解 “这和 mixins 类似,区别在于,组件自身的选项会比要扩展的源组件具有更高的优先级。” 这句话。都是通过mergeOptions,mixins和extends为什么会有不一样的优先级。

关于vue技术内幕中数据响应系统中watch那一部分

image

这里foreach循环读取data.a.b在这里首先data = data.a 然后data= data.b,先调用了data.a的get方法,此时a属性的dep中push了watch中给a.b属性设置的fn,那这样岂不是会导致当我在set data.a属性的时候触发watch中给a.b属性设置的fn吗?

关于开始标签的闭合部分

关于开始标签的闭合部分:

const startTagClose = /^\s*(/?)>/

在chrome上,如果是一个 > 不是一个一元签标的闭合方式。在捕获组中的分显示空字符串,而不是undefined

Confirm several typos with you

Location: 6vue-init-start.md
1.hasHandler 这个变量就定义在当前文件,如下:
const hasHandler = {
has (target, key) {
// has 变量是真实经过 in 运算符得来的结果
const has = key in target
~-----------------------------------------------------
hasHandler 和 has 均为常量.
~-----------------------------------------------------
2.上面的代码由于 render 函数时我们手动书写的,所以 render 函数并不会被包裹在 with 语句块内,
~-----------------------------------------------------
“函数时” or “函数是” ?
~-----------------------------------------------------
3、最后我们注意到 callHook 函数的最后有这段一段代码:
~-----------------------------------------------------
“最后有这段一段代码:” or “最后有这样一段代码:” ?
~-----------------------------------------------------

$nextTick关于microtask优先于 (macro)task执行

nextTick 的实现

当调用栈空闲后每次事件循环只会从(macro)task 中读取一个任务并执行,而在同一次事件循环内会将 microtask 队列中所有的任务全部执行完毕,且要先于 (macro)task。

执行完一次(macro)task任务之后,会执行所有microtask。microtask优先于第二次(macro)task任务执行是否更合理。

文章中错别字疑问

在5vue-merge.md文件中:
1)这个时候则直接返回 mergeDataOrFn 的函数执行结果,但是会多透传一个参数 vm:
疑问:多透传? “透” 字是多余的吗?
2)那么 mergeHook 函数时怎样合并生命周期选项的呢?我们看看 mergeHook 函数的代码,如下:
疑问:“函数时” ? 还是 “函数是”
3)整个函数体由三组三目运算符组成,有一点值得大家学习的就是这里写三目运算符的方式,是不是感觉非常的清晰易读?那么这段代码的分析我们同样使用与上面代码相同的格式来写:
疑问:“非常的清晰易读” 应该为 “非常地清晰易读”

你好,关于选项 el、propsData 的合并策略里面的一段代码,有个问题.

//41行

if (process.env.NODE_ENV !== 'production') {
  strats.el = strats.propsData = function (parent, child, vm, key) {
    if (!vm) {
      warn(
        `option "${key}" can only be used during instance ` +
        'creation with the `new` keyword.'
      )
    }
    return defaultStrat(parent, child)
  }
}

该段代码中的defaultStrat是在下文中声明的,const 不是不会提升变量么?为什么defaultStrat可以被执行?是因为打包后会被处理么?
//240行

/**
 * Default strategy.
 */
const defaultStrat = function (parentVal: any, childVal: any): any {
  return childVal === undefined
    ? parentVal
    : childVal
}

ps:感谢作者的指导

实例对象代理访问数据 data,优先级描述有误

在<实例对象代理访问数据 data>一节中写道: ”props优先级 > data优先级 > methods优先级“
实际优先级是否应该是 ”props优先级 > methods优先级 > data优先级 “
因为initMethod执行在前,只是Vue的warn message 写的看起来像data的优先级比较高

Please consider translation to English

Hi,

I'm really looking forward, if it would be possible to have this awesome project translated to Eng!

You did a great job. Awesome project!
Will manage somehow with google.translate for now ;) Thanks a lot!

Regards,
D.

English

Is there an English language version of this?

看您的源码分析,关于同步队列更新不懂的地方

在methods里面改变两个属性值this.a='更新一';this.b='更新二';如果使用同步队列更新,为什么会渲染两次?
我的理解:在同一个tick里执行this.a='更新一';this.b='更新二';执行了两次run()和patch()。这些都是同一个tick里面的宏任务,是发生在渲染之前的,应该只会渲染一次。
求大佬解答,非常感谢

关于$nextTick执行过程中提到的重新渲染

8vue-reactive-dep-watch.md文章中有如下一段:

callbacks = [
  flushSchedulerQueue, // queue = [renderWatcher]
  () => {
    this.name = 'hcy'
    this.$nextTick(() => { console.log('第二个 $nextTick') })
  }
]

接下来主线程处于空闲状态(调用栈清空),开始执行 microtask 队列中的任务,即执行 flushCallbacks 函数,flushCallbacks 函数会按照顺序执行callbacks数组中的函数,首先会执行flushSchedulerQueue函数,这个函数会遍历queue中的所有观察者并重新求值,完成重新渲染,在完成渲染之后,本次更新队列已经清空,queue会被重置为空数组,一切状态还原。接着会执行如下函数:

() => {
  this.name = 'hcy'
  this.$nextTick(() => { console.log('第二个 $nextTick') })
}

这里提到在microtask中的任务flushCallbacks在执行callbacks数组,此时数组中有上面的两个函数,而这个函数会遍历queue中的所有观察者并重新求值,完成重新渲染,在完成渲染之后这句话提到重新渲染,这里的重新渲染是指的浏览器的渲染吗?我在翻查关于eventloop的文章时,写的都是浏览器的渲染发生在两个(macro)task之间,且是否执行该次渲染根据浏览器的render策略决定,具体可查看深入探究 eventloop 与浏览器渲染的时序问题
所以,我觉的这里的重新渲染应该是指的DOM更新吧,而这里是等microtask都执行完后,也就是后面的嵌套的$nextTick(应为它也会添加到microtask队列中)也执行完之后,得到最终的DOM,然后会触发浏览器重新渲染,得到渲染后的页面。

以上疑问如果有问题,还请大佬给指正一下,3Q。

关于覆盖预定义配置的疑问

src/core/util/options.js
2018-07-17 11 23 34
validateComponentName这个function中,config这个变量是从 src/core/config.js这个文件导入的,
2018-07-17 11 26 16

是如何做到覆盖config的isReservedTag方法的? 这个config并不是 Vue的config吧?它是import进来的。
2018-07-17 11 34 07

文章上的源码与vue的不一致了

初始化之 initEvents这篇源码分析里的
createComponentInstanceForVnode函数已经不一样了。告知一下作者

export function createComponentInstanceForVnode (
  vnode: any, // we know it's MountedComponentVNode but flow doesn't
  parent: any, // activeInstance in lifecycle state
  parentElm?: ?Node,
  refElm?: ?Node
): Component {
  const vnodeComponentOptions = vnode.componentOptions
  const options: InternalComponentOptions = {
    _isComponent: true,
    parent,
    propsData: vnodeComponentOptions.propsData,
    _componentTag: vnodeComponentOptions.tag,
    _parentVnode: vnode,
    _parentListeners: vnodeComponentOptions.listeners,
    _renderChildren: vnodeComponentOptions.children,
    _parentElm: parentElm || null,
    _refElm: refElm || null
  }
  // check inline-template render functions
  const inlineTemplate = vnode.data.inlineTemplate
  if (isDef(inlineTemplate)) {
    options.render = inlineTemplate.render
    options.staticRenderFns = inlineTemplate.staticRenderFns
  }
  return new vnodeComponentOptions.Ctor(options)
}

vue.js现在的代码:

export function createComponentInstanceForVnode (
  vnode: any, // we know it's MountedComponentVNode but flow doesn't
  parent: any, // activeInstance in lifecycle state
): Component {
  const options: InternalComponentOptions = {
    _isComponent: true,
    _parentVnode: vnode,
    parent
  }
  // check inline-template render functions
  const inlineTemplate = vnode.data.inlineTemplate
  if (isDef(inlineTemplate)) {
    options.render = inlineTemplate.render
    options.staticRenderFns = inlineTemplate.staticRenderFns
  }
  return new vnode.componentOptions.Ctor(options)
}

调用栈注明

膜拜楼主, 提个小小的建议, 当介绍的函数调用栈比较深的时候, 可以把 Chrome DevTools 里的调用栈截图贴出来, 感觉这样会更通俗易懂

关于 Observer 构造函数的理解偏差

Observer 构造函数 中写道:

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that has this object as root $data

  constructor (value: any) {
    // 省略...
  }

  walk (obj: Object) {
    // 省略...
  }
  
  observeArray (items: Array<any>) {
    // 省略...
  }
}

可以清晰的看到 Observer 类的实例对象将拥有三个实例属性,分别是 value、dep 和 vmCount 以及两个实例方法 walk 和 observeArray。Observer 类的构造函数接收一个参数,即数据对象。下面我们就从 constructor 方法开始,研究实例化一个 Observer 类时都做了哪些事情。

class中声明的应该是原型方法吧?所以应该是 Observer 类的实例对象拥有 walkobserveArray 两个原型方法吧?

这算是理解上的偏差么?

疑似错误

链接:揭开数据响应系统的面纱

位置:那么经过 def 函数处理之后,data 对象应该变成如下这个样子下边这一段代码;

const data = {
  a: 1,
  // __ob__ 是不可枚举的属性
  __ob__: {
    value: data, // value 属性指向 data 数据对象本身,这是一个循环引用
    dep: dep实例对象, // new Dep()
    vmCount: 0
  }
}

Observerconstructor中调用的def的第三个参数是this,即生成的Observer对象,所以上边的value属性值应是observer(Observer对象),即

const data = {
  a: 1,
  // __ob__ 是不可枚举的属性
  __ob__: {
    value: observer, // 生成的Observer对象,它的value属性才是data
    dep: dep实例对象, // new Dep()
    vmCount: 0
  }
}

自己试了下也的确是这样的。

console.log(data.__ob__.value === data); // true

For the reader

@ALL

  1. Thank you for reading. In fact, if you understand the existing chapters, you can basically go and explore it yourself. You don't need me to explain it.
  2. I will prepare a thorough article for everyone to have a clear vein, and the road after that will depend on everyone to go.
  3. I didn't feel very strange when analyzing the code written by others, but I submitted two PRs to Vue two days ago. I found that I wanted to modify the explanations in the previous article to match the new changes, but when I tried to explain what I wrote. I suddenly felt --" just like I was eating my own vomit."
  4. Do not publish books (not enough level), do not sell money (a clear conscience).
  5. Again... I will write another article to help you with your thoughts. It will cover all aspects, and this may be the last one.
  6. I will focus on the substantial contribution to open source projects.

@ALL I love you.

会继续更新吗?

代码生成部分的解析会更新吗?Vue3.0出来之后会持续更新该项目吗?

关于几个package.json的配置属性的作用

您好,最近在拜读您的Vue技术内幕,感觉十分棒!一边跟随您的思路一边对照源码,其中有几个属性很是迷惑。您未曾提及,我也查询了一番,未能找到满意的答案,在这里发起该 Issue 还望指教。这三个属性分别是pck.unpkgpck.jsdelivrpck.typings。下面是截图
image

谢谢您,祝您工作愉快!

无耻的催更😝😝😝

作者写的太好了,最重要的是还开源,我觉得作者很了不起

so,什么时候更新😝😝😝

关于initData中vm.$options.data的类型判断的问题

因为beforeCreate钩子是在initState之前执行的,所以如果我在beforeCreate钩子中改变了vm.$options.data的话,这个initData中的类型判断就是有必要的了

const app = new Vue({
    el: '#app',
    data: {
        name: 'a'
    },
    beforeCreate () {
        this.$options.data = {
            name: 'b'
        }
    }
})

麻烦样式保持统一

跟vue 文档的文字类型 字体颜色 字号的保持统一..

保证用户切换的一致性.

关于规范化Inject参数问题normalizeInject(child, vm)

function normalizeInject (options: Object, vm: ?Component) {
  const inject = options.inject
  if (!inject) return
  const normalized = options.inject = {}
  if (Array.isArray(inject)) {
    ...
  } else if (isPlainObject(inject)) {
    for (const key in inject) {
      const val = inject[key]
      normalized[key] = isPlainObject(val)
        ? extend({ from: key }, val)
        : { from: val }
    }
  } else if (process.env.NODE_ENV !== 'production') {
    ...
  }
}
inject: {
  data1,
  d2: 'data2',
  data3: { someProperty: 'someValue' }
}
inject: {
  'data1': { from: 'data1' },
  'd2': { from: 'data2' },
  'data3': { from: 'data3', someProperty: 'someValue' }
}

请问data3的someProperty是如何被赋值过去的?

图片404

好几个页面都这样。看到文中说下图上图的时候愣是没发现图片。

image
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.