好家伙,

 代码出了点bug,暂时只能实现这两种形式

完整代码已开源https://github.com/Fattiger4399/analytic-vue.git

Vue:watch的多种使用方法

watch有非常多种使用方式,我们要对其进行分类讨论处理

1.初始化:

//initState.js

if (opts.watch) {
initWatch(vm);
}

initWatch()方法

function initWatch(vm) {
//1 获取watch
let watch = vm.$options.watch
console.log(watch)
//2 遍历 { a,b,c}
for (let key in watch) {
//2.1获取 他的属性对应的值 (判断)
let handler = watch[key] //数组 ,对象 ,字符,函数
if (Array.isArray(handler)) {//数组 []
handler.forEach(item=>{
createrWatcher(vm,key,item)
})
} else {//对象 ,字符,函数
//3创建一个方法来处理
createrWatcher(vm,key,handler)
}
}
}

createrWatcher()

//格式化处理
//vm 实例
//exprOrfn key
//hendler key对应的值
//options 自定义配置项 vue自己的为空,用户定义的才有
function createrWatcher(vm,exprOrfn,handler,options){
//3.1 处理handler
if(typeof handler ==='object'){
options = handler; //用户的配置项目
handler = handler.handler;//这个是一个函数
}
if(typeof handler ==='string'){// 'aa'
handler = vm[handler] //将实例行的方法作为 handler 方法代理和data 一样
}
//其他是 函数
//watch 最终处理 $watch 这个方法
// console.log(vm,"||vm")
// console.log(exprOrfn,"||exprOrfn")
// console.log(handler,"||handler")
// console.log(options,"||options") return vm.$watch(vm,exprOrfn,handler,options)
}

原型上挂$watch方法

export function stateMixin(vm) {
console.log(vm,6666)
//列队 :1就是vue自己的nextTick 2用户自己的
vm.prototype.$nextTick = function (cb) { //nextTick: 数据更新之后获取到最新的DOM
// console.log(cb)
nextTick(cb)
},
vm.prototype.$watch =function(Vue,exprOrfn,handler,options={}){ //上面格式化处理
// console.log(exprOrfn,handler,options)
//实现watch 方法 就是new watcher //渲染走 渲染watcher $watch 走 watcher user false
// watch 核心 watcher
let watcher = new Watcher(Vue,exprOrfn,handler,{...options,user:true}) if(options.immediate){
handler.call(Vue) //如果有这个immediate 立即执行
}
} }

2.watcher.js

watcher类

class Watcher {
//vm 实例
//exprOrfn vm._updata(vm._render())
constructor(vm, exprOrfn, cb, options) {
// 1.创建类第一步将选项放在实例上
this.vm = vm;
this.exprOrfn = exprOrfn;
this.cb = cb;
this.options = options;
// 2. 每一组件只有一个watcher 他是为标识
this.id = id++
this.user = !!options.user
// 3.判断表达式是不是一个函数
this.deps = [] //watcher 记录有多少dep 依赖
this.depsId = new Set()
if (typeof exprOrfn === 'function') {
this.getter = exprOrfn
}else{ //{a,b,c} 字符串 变成函数
this.getter =function(){ //属性 c.c.c
let path = exprOrfn.split('.')
let obj = vm
for(let i = 0;i<path.length;i++){
obj = obj[path[i]]
}
return obj //
}
}
// 4.执行渲染页面
this.value = this.get() //保存watch 初始值 }
addDep(dep) {
//去重 判断一下 如果dep 相同我们是不用去处理的
let id = dep.id
// console.log(dep.id)
if (!this.depsId.has(id)) {
this.deps.push(dep)
this.depsId.add(id)
//同时将watcher 放到 dep中
// console.log(666)
dep.addSub(this) }
// 现在只需要记住 一个watcher 有多个dep,一个dep 有多个watcher
//为后面的 component
}
run() { //old new
let value = this.get() //new
let oldValue = this.value //old
this.value = value
//执行 hendler (cb) 这个用户wathcer
if(this.user){
this.cb.call(this.vm,value,oldValue)
}
}
get() {
// Dep.target = watcher pushTarget(this) //当前的实例添加
const value = this.getter()// 渲染页面 render() with(wm){_v(msg,_s(name))} ,取值(执行get这个方法) 走劫持方法
popTarget(); //删除当前的实例 这两个方法放在 dep 中
return value
}
//问题:要把属性和watcher 绑定在一起 去html页面
// (1)是不是页面中调用的属性要和watcher 关联起来
//方法
//(1)创建一个dep 模块
updata() { //三次
//注意:不要数据更新后每次都调用 get 方法 ,get 方法回重新渲染
//缓存
// this.get() //重新渲染
queueWatcher(this)
}
}

3.看看效果

<body>
<div id="app">{{a}}</div>
<script src='./dist/vue.js'></script>
<script>
let vm = new Vue({
el: "#app",
data: {
a: 1,
b:[1,2],
c:{c:{c:100}}
},
methods:{
aa(){
console.log(2000)
}
},
//watch 基本使用方式
//1 属性 :方法(函数)
//2 属性 :数组
//3 属性 :对象
//4 属性 :字符串
watch: {
'c.c.c'(newValue,oldValue){
console.log(newValue,oldValue,'||this isnewValue,oldValue from c.c.c')
}, a:{
handler(){ //
console.log('a数据更新')
},
immediate:true },
// a:'aa',
}
})
vm.a = 100
// vm.b[1] = 2
console.log(vm.c.c.c=2000)
</script>
</body>

 

Vue源码学习(十三):实现watch(一):方法,对象的更多相关文章

  1. Vue源码学习1——Vue构造函数

    Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...

  2. Vue源码学习三 ———— Vue构造函数包装

    Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...

  3. Vue源码学习二 ———— Vue原型对象包装

    Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...

  4. 最新 Vue 源码学习笔记

    最新 Vue 源码学习笔记 v2.x.x & v3.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 v2.x.x & v3.x.x ...

  5. 【Vue源码学习】依赖收集

    前面我们学习了vue的响应式原理,我们知道了vue2底层是通过Object.defineProperty来实现数据响应式的,但是单有这个还不够,我们在data中定义的数据可能没有用于模版渲染,修改这些 ...

  6. VUE 源码学习01 源码入口

    VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...

  7. Vue源码学习(一):调试环境搭建

    最近开始学习Vue源码,第一步就是要把调试环境搭好,这个过程遇到小坑着实费了点功夫,在这里记下来 一.调试环境搭建过程 1.安装node.js,具体不展开 2.下载vue项目源码,git或svn等均可 ...

  8. Vue 源码学习(1)

    概述 我在闲暇时间学习了一下 Vue 的源码,有一些心得,现在把它们分享给大家. 这个分享只是 Vue源码系列 的第一篇,主要讲述了如下内容: 寻找入口文件 在打包的过程中 Vue 发生了什么变化 在 ...

  9. 【Vue源码学习】响应式原理探秘

    最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...

  10. mybatis源码学习:从SqlSessionFactory到代理对象的生成

    目录 一.根据XML配置文件构建SqlSessionFactory 二.通过SqlSessionFactory创建SqlSession 三.getMapper获取动态代理对象 一.根据XML配置文件构 ...

随机推荐

  1. 安装Hadoop单节点伪分布式集群

    目录 安装Hadoop单节点伪分布式集群 系统准备 开启SSH 安装JDK 安装Hadoop 下载 准备启动 伪分布式模式安装 配置 配饰SSH免密登录本机 测试启动 单节点安装YARN 伪分布式集群 ...

  2. PDF书签的编辑器,基于(python、Tkinter)

    使用 脚本 在github下载源码. 安装python3 安装必要的python包 pip install numpy pip install pandas pip install PyMuPDF p ...

  3. Unity自定义类使用携程--自身不继承MonoBehaviour

    [TOC] 参考: https://www.jianshu.com/p/67f498cb839b 话不多说,直接上代码 1 using System.Collections; 2 using Unit ...

  4. C语言基础-基础指针

    文章目录 指针 前言 1.什么是指针 2.指针的使用 (1)指针的定义 (2)指针的赋值 (3)指针类型 (4)如何使用指针 3.野指针 (1)导致野指针的原因 ① 未初始化指针 ②指针越界访问 ③指 ...

  5. SQLServer 数据库 Money 和 Float 类型运算的奇怪显现

    SQLServer 数据库 Money和 Float类型运算的奇怪显现 1.1 背景 1.2 场景描述 1.3 原因及解决办法 1.1 背景 最近在做一个优化的项目 1.2 场景描述 DECLARE ...

  6. fastjson 1.2.80 漏洞浅析及利用payload

    0x01 说明 在fastjson的1.2.80版本中可以通过将依赖加入到java.lang.Exception 期望类的子类中,绕过checkAuto. 0x02 简析 { "@type& ...

  7. 【博客重构之路】webman-admin安装指南

    原文地址[博客重构之路]webman-admin安装指南 视频地址[bilibili] webman是什么 webman是一款基于workerman开发的高性能HTTP服务框架.webman用于替代传 ...

  8. loader的三种配置方式

    在这篇 webpack处理css资源 文章中使用几个常用的loader 来编译 css 代码. 但其实 loader 的配置方式不止一种,一起来看看其它方式~ 在 webpack.config.js ...

  9. [nginx]编译安装openresty

    前言 OpenResty是一个基于Nginx和Lua的高性能Web平台,其内部集成了大量精良的Lua库.第三方模块以及大多数的依赖项.用于方便地搭建能够处理超高并发.扩展性极高的动态 Web 应用.W ...

  10. 手写 Vuex4 源码

    本文首发于掘金,未经许可禁止转载 Vuex4 是 Vue 的状态管理工具,Vuex 和单纯的全局对象有以下两点不同: Vuex 的状态存储是响应式的 不能直接改变 store 中的状态.改变 stor ...