Vue源码学习(十三):实现watch(一):方法,对象
好家伙,
代码出了点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(一):方法,对象的更多相关文章
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- Vue源码学习三 ———— Vue构造函数包装
Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...
- Vue源码学习二 ———— Vue原型对象包装
Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...
- 最新 Vue 源码学习笔记
最新 Vue 源码学习笔记 v2.x.x & v3.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 v2.x.x & v3.x.x ...
- 【Vue源码学习】依赖收集
前面我们学习了vue的响应式原理,我们知道了vue2底层是通过Object.defineProperty来实现数据响应式的,但是单有这个还不够,我们在data中定义的数据可能没有用于模版渲染,修改这些 ...
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- Vue源码学习(一):调试环境搭建
最近开始学习Vue源码,第一步就是要把调试环境搭好,这个过程遇到小坑着实费了点功夫,在这里记下来 一.调试环境搭建过程 1.安装node.js,具体不展开 2.下载vue项目源码,git或svn等均可 ...
- Vue 源码学习(1)
概述 我在闲暇时间学习了一下 Vue 的源码,有一些心得,现在把它们分享给大家. 这个分享只是 Vue源码系列 的第一篇,主要讲述了如下内容: 寻找入口文件 在打包的过程中 Vue 发生了什么变化 在 ...
- 【Vue源码学习】响应式原理探秘
最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...
- mybatis源码学习:从SqlSessionFactory到代理对象的生成
目录 一.根据XML配置文件构建SqlSessionFactory 二.通过SqlSessionFactory创建SqlSession 三.getMapper获取动态代理对象 一.根据XML配置文件构 ...
随机推荐
- study the docker network of macvlan
Introduce: 在 Macvlan 出现之前,我们只能为一块以太网卡添加多个 IP 地址,却不能添加多个 MAC 地址,因为 MAC 地址正是通过其全球唯一性来标识一块以太网卡的,即便你使用了创 ...
- IIC、SPI、UART三者对比
下面将对比三者的各自差异: 参考资料: 1.(112条消息) UART, SPI, IIC的详解及三者的区别和联系_iic spi uart_静思心远的博客-CSDN博客
- 「Python实用秘技16」快速提取字体子集
本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills 这是我的系列文章「Python实用秘技」的第16 ...
- 医疗知识图谱问答 ——Neo4j 基本操作
前言 说到问答机器人,就不得不说一下 ChatGPT 啦.一个预训练的大预言模型,只要是人类范畴内的知识,似乎他回答得都井井有条,从写文章到写代码,再到解决零散琐碎的问题,不光震撼到我们普通人,就百度 ...
- PB从入坑到放弃(六)动态SQL应用
写在前面 动态 SQL 语句是部分或者整个 SQL 语句在运行时才能确定,可以更好的与用户进行交互,大大提高了SQL的灵活性 一.执行SQL语句 1.1 执行无入参SQL ① 语法 EXECUTE I ...
- 使用MediatR和FluentValidation实现CQRS应用程序的数据验证
本文将重点介绍如何通过MediatR的管道功能将FluentValidation集成到项目中实现验证功能. 什么是CQRS? CQRS(Command Query Responsibility Seg ...
- 如何找到docker容器中的网卡外联的veth pair的另一张网卡
1.概述 在Docker容器中,每个容器都有一个或多个网络接口(网卡),用于连接容器内部与宿主机或其他容器进行通信.这些网络接口中的一些可能是veth pair,也就是虚拟以太网对,它们以成对的方式存 ...
- 《Linux基础》06. 进程管理 · 服务管理
@ 目录 1:进程管理 1.1:查看进程 1.1.1:ps 1.1.2:pstree 1.1.3:top 1.2:终止进程 1.2.1:kill 1.2.2:killall 2:服务管理 2.1:运行 ...
- 应用程序接口(API)安全的入门指南
什么是 API? 对于初学者来说,API 是指为两个不同的应用之间实现流畅通信,而设计的应用程序编程接口.它通常被称为应用程序的"中间人".由于我们需要保护用户的持有数据. ...
- iOS发送探针日志到日志系统的简单实现
通过参考Testin的SDK实现方式,我们大致可以确定他们背后的实现方式: 首先,通过加载Testin的SDK,然后收集各种七七八八的数据,再通过socket发送数据到云端. 云端我们已经有了,就是h ...