此篇文章主要是从应用及源码层面讲解vue部分常用api,阅读起来可能略有难度,新手可以看《从文档开始,重学vue(上)》

示例代码均在vue-cli3中完成

Vue.extend()

可以使用 extend 创建一个子类,该方法通常用于构建全局组件,如弹框组件等,下面我们就用它来制作个全局alert组件吧

  1. 首先我们需要一个alert.vue组件,组件很简单就接受一个参数,然后有两个控制显示隐藏的方法
  2. 需要把alert挂载到body 注意extend的使用方式
  3. 使用

使用之前别忘了在main.jsuse一下

import Alert from "./components/Alert/create";Vue.use(Alert)

用起来也非常方便,如下:

mounted(){    this.$alert('公众号,码不停息')}

上面我们使用extend直接给他传了个组件进去,其实我们也可以给extend的配置对象,如下:

Vue.extend({ template: "{{msg}}", data() {   return {     msg: "码不停息"   }; }});

下面我们通过源码来看看在vue内部extend都做了哪些事情,关键性代码已经加上注释主要做的事情就是把通过extend挂载的组件初始化,并完善里面的options最后返回组件

Vue.nextTick()

如果想理解清楚nextTick,需要我们了解vue异步队列javascript(确切的说是浏览器)的事件循环机制

  • vue异步更新队列
  • 事件循环机制

可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替(Vue官网)

可以简单的总结为Vue实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新,他的策略就是同一事件循环中的所有数据变化完成之后,再统一进行视图更新,如果在这个过程中想要操作dom就比较棘手了,而Vue.nextTick就是来解决这样的问题,如下:

  
{{ time }}

export default { data() { return { time: "" }; }, methods: { getDom() { return document.getElementById("time").innerHTML; } }, mounted() { this.time = new Date().toLocaleTimeString(); console.log("获取time", this.getDom()); //获取不到 this.$nextTick(() => { console.log("获取time", this.getDom()); //可以获取到 }); }};


可以看到,当我们给time赋值后直接通过原生dom获取值是获取不到的,而用this.$nextTick(callback)就可以获取到了,那nextTick在内部做了什么呢?我们找到相应的源码可以看出,当我们在代码中执行$nextTick方法时,内部是调用了nextTick,那我们再来看看nextTick方法里面都有什么?原来nextTick方法把我们传的函数都push到了一个callback数组里,那这个数组是什么时候执行呢?为了方便看,我把相关代码都复制出来如下:代码较长,可以放大观看,关键代码已给出注释,主要逻辑如下:

用户调用$nextTick(callback) -> 把用户传入函数push到callback数组 -> 检测当前平台环境决定使用哪种方式处理异步 -> 执行flushCallbacks函数 -> flushCallbacks中循环执行callback

因为微任务会在当前宏任务执行完毕后立即执行,这样就能保证在执行$nextTick()的时候,当前宏任务(包括页面渲染)已经执行完毕

Vue.set()

Vue.set()设置的值是响应式,当我们需要对 复杂数据类型 新增属性和值,同时需要新增的值是 响应式 的时候就需要使用该api 如下所示:

  1. 直接给对象赋一个新的属性和新值
  
公众号: {{ userInfo.name }}
作者:{{ userInfo.author || "暂无数据" }}

export default { data() { return { userInfo: { name: "码不停息" } }; }, methods: {}, mounted() { this.userInfo.author = "刘小灰"; // 注意 userInfo开始没有author属性 }};

渲染结果如下, 数据没有出来,新增的author不是响应式

  1. 我们再用Vue.set()给对象赋一个新的属性和新值
  
公众号: {{ userInfo.name }}
作者:{{ userInfo.author || "暂无数据" }}

export default { data() { return { userInfo: { name: "码不停息" } }; }, methods: {}, mounted() { this.$set(this.userInfo, "author", "刘小灰"); //使用set赋值 }};

再看看结果,新增的author是响应式

除了基本使用,我们来思考下Vue为什么要设置这个api,为什么直接通过.语法添加的属性就不是响应式的呢? 使用this.$set()是有如何做到响应式的呢?

我们来源码中找答案

简单了解下响应式

响应式的具体表现是当我们把data中的属性和页面绑定后,改变data中的数据后,页面会自动更新,那Vue是如何实现响应式的呢?

不难得出在vue2.x中是使用Object.defineProperty对数据进行劫持来实现响应式,当我们初始化的时候,会把每一个数据都进行依赖收集,内部主要是通过遍历及递归来实现,如下(关键代码已给出注释):下面我们来看看核心方法defineReactive都干了什么事情(关键代码已给出注释)

大体流程

初始化 -> 执行Observer -> 如果是数组特殊处理,否则遍历子 -> 执行walk -> defineReactive进行响应式处理,如果数据中对象嵌套,递归之,否则进行依赖收集,确保全部数据都经过Object.defineProperty的洗礼 -> 响应式处理完毕

这时问题来了, 如果你在代码中给某个对象通过.语法新加个属性,这个时候初始化过程早已结束,新加的属性并没有经过Object.defineProperty的洗礼,自然不会变成响应式数据,这个时候我们就需要使用Vue.set()方法,让数据变成响应式,那set中是如何做的呢?其实就是重新调了下Object.definePropertyset方法进行依赖收集即可

关于Vue是如何对数组进行特殊处理的,可以看Object.defineProperty是如何实现对数组的监听

Vue.use()

安装 Vue 插件使用,use的源码比较短我们直接看源码:如下(关键代码已给出注释)所以在我们平常使用时,我们有两种使用方式

方式一:Vue.use({  install(vue){        }})方式二:Vue.use((vue)=>{})

无论是哪种方式,Vue都会把vue实例在回调中返回回来供我们使用

最后

最后我想说说为什么我们要学习源码,我觉得源码能不能学透并不重要(当然,如果你可以把源码彻底看懂也再好不过),对我们大部分人来说,学习源码最重要的目的是 查漏补缺 ,看大佬们是怎么写代码,是怎么组织代码,而这种能力不是我们多做几个项目,多发几个ajax请求能够得到的,就拿自己来说,看了源码后我发现自己对函数式编程,对发布订阅模式掌握的还不是不好,然后自己花些时间再加强下这方面的理解,然后把自己理解到的知识再在看源码中得以升华,我感觉这是最酷的!

最后的最后

交个朋友吧,关注微信公众号,拉你进群,和一群志同道合的人学习源码

vue process.env获取不到_从文档开始,重学vue(下)源码级别相关推荐

  1. php验证码手册,验证码_专题_帮助文档_Thinkphp手册

    验证码_专题_帮助文档_Think Think/Verify类可以支持验证码的生成和验证功能. 生成验证码 下面是最简单的方式生成验证码: seover" style=" marg ...

  2. api数据接口文档_接口文档示例(Taobao/jd/pinduoduo/开放接口调用)

    api数据接口文档_接口文档示例 本文主要是提供了一个接口文档的范文,内容修订历史.目录.时序图.接口要素描述.接口说明.使用示例.字典.FAQ.  使用MD格式文档(makedown),选择原因,容 ...

  3. java+vue实现前后端导出html的word文档

    java+vue实现前后端导出html的word文档 该内容主要是完成项目中实战导出word文档,而且不需要其他的依赖,原生的写法即可! 本项目架构: PS:不是这个架构的话看下逻辑就好,赶紧找别的博 ...

  4. HTML5汽车网页设计成品_学生DW汽车静态网页设计代做_web课程设计网页制作_宽屏大气汽车自驾游网站模板html源码...

    HTML5汽车网页设计成品_学生DW汽车静态网页设计代做_web课程设计网页制作_宽屏大气汽车自驾游网站模板html源码 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML ...

  5. HTML5汽车网页设计成品_学生DW汽车静态网页设计代做_web课程设计网页制作_宽屏大气汽车自驾游网站模板html源码

    HTML5汽车网页设计成品_学生DW汽车静态网页设计代做_web课程设计网页制作_宽屏大气汽车自驾游网站模板html源码 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML ...

  6. 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 使用反射获取方法创建本应用的 dexElements | 各版本创建 dex 数组源码对比 )

    文章目录 一.不同 Android 系统创建 dex 数组源码对比 二.不同 Android 系统创建 dex 数组源码对比 三. Android 5.1 及以下系统反射方法并创建 Element[] ...

  7. php方法帮助文档,Trace方法_帮助文档_Thinkphp手册

    Trace方法_帮助文档_Think 页面Trace只能用于有页面输出的情况,但是trace方法可以用在任何情况,而且trace方法可以用于AJAX等操作. Trace方法的格式:trace('变量' ...

  8. ssm+Vue计算机毕业设计在线答题系统(程序+LW文档)

    ssm+Vue计算机毕业设计在线答题系统(程序+LW文档) 项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe ...

  9. java计算机毕业设计vue基层社区管理服务网MyBatis+系统+LW文档+源码+调试部署

    java计算机毕业设计vue基层社区管理服务网MyBatis+系统+LW文档+源码+调试部署 java计算机毕业设计vue基层社区管理服务网MyBatis+系统+LW文档+源码+调试部署 本源码技术栈 ...

最新文章

  1. ObjectDataSource未能找到带参数的非泛型方法的解决
  2. MySQL 获得当前日期时间 函数
  3. 用于参考的学生信息管理系统(数据库简单 可自己参考创建)
  4. iOS 自动构建套件 - flow.ci + fir.im + Coding
  5. 委托的Invoke 和 BeginInvoke 与Control的Invoke和BeginInvoke(转-因为写得很好)
  6. springboot整合kafka和netty服务简单实例
  7. CreateDesktop 创建虚拟桌面
  8. Fletcher-Reevers Conjugate Descent和Steepest Descent两种算法中伪代码的区别
  9. nginx 如何解析php文件php-fpm的解释
  10. 【华为云技术分享】探索软件复杂性简洁之道
  11. 官方暗示小米MIX Alpha重磅信息:屏下摄像头要成真?
  12. Andorid AlertDialog 点击后自动消失_Andorid-APP 安全(五)之android取证-文件系统与数据结构...
  13. LeetCode - Merge Two Sorted Lists
  14. A*算法的原理和实现
  15. 如何设计一个秒杀系统(完整版)
  16. 解决Google Earth谷歌地球无法连接服务器问题
  17. FIRST 和 FOLLOW求解
  18. React实现微信公众号支付
  19. C# LeetCode刷题 - Leetcode 306. 累加数 - 题解
  20. 有关php地英语文章,实用英语短句-PHP教程,其它文章

热门文章

  1. 苹果X可以升级5G吗_苹果x可以用5g网络吗
  2. 笨办法学linux dhcp,iptables使用指南(上)
  3. php hasmany,浅谈laravel orm 中的一对多关系 hasMany
  4. java 在已有的so基础上封装jni_[干货]再见,Android JNI 封装
  5. 【转】01.Dicom 学习笔记-DICOM C-Store 消息服务
  6. 第二节:框架前期准备篇之AutoFac常见用法总结
  7. 将 Fortinet 连接到
  8. java正则表达式 ascii,是否可以检查字符串是否在Java中仅包含ASCII?
  9. 【牛客 - 315C】排列(思维,贪心,同优则立证明法)
  10. *【CodeForces - 791B】Bear and Friendship Condition (图论,判断完全图,dfs乱搞或带权并查集)