【Vue3源码学习】— CH2.6 effect.ts:详解
effect.ts:详解
- 1. 理解activeEffect
- 1.1 定义
- 1.2 通过一个例子来说明这个过程
- a. 副作用函数的初始化
- b. 执行副作用函数前
- c. 访问state.count
- d. get拦截器中的track调用
- e. 修改state.count时的set拦截器
- f. trigger函数中的依赖重新执行
- 1.3 实战应用
- 1.4 activeEffect的作用:
- 2. 理解ReactiveEffect
- 2.1 定义
- 2.2 源码解析
- 2.3 重要属性解释
- 3. 理解effect函数
- 3.1 定义
- 3.2 源码解析
- 3.3 工作原理
- 3.3.1 封装副作用函数
- 3.3.2 自动执行和响应
- 3.3.3 控制执行
- 3.4 runner解析
- 4. 小结
- 4.1 副作用函数的初始化
- 4.2 依赖收集(Tracking)
- 4.3 触发更新(Triggering)
- 4.4 重新执行副作用函数
在Vue 3的响应式系统中,
effect.ts
是一个核心文件,它负责实现副作用函数(
ReactiveEffect
)的注册、追踪和触发更新机制。这个机制是Vue 3自动响应式更新的基石,允许我们构建高效且响应式的用户界面。以下是对
effect.ts
文件关键部分的详细解析。
1. 理解activeEffect
在之前的章节中,我们看到track
函数建立依赖,即将当前访问的属性与activeEffect
建立依赖关系。然而,直接从effect.ts
里的源码看起来,activeEffect
的含义可能不是很明显。因此,在学习这部分源码时,首先需要清楚activeEffect
的概念。
1.1 定义
activeEffect是一个全局变量,用于存储当前正在执行的ReactiveEffect实例。当Vue的响应式系统执行一个副作用函数时,它会把这个副作用函数对应的ReactiveEffect实例设置为activeEffect,这样在副作用函数执行期间,任何响应式数据的访问都能通过activeEffect关联起来,实现依赖追踪。
1.2 通过一个例子来说明这个过程
import { reactive, effect } from 'vue';//使用reactive创建一个响应式状态state
const state = reactive({ count: 0 });//通过effect注册一个副作用函数,这个函数简单地打印出state.count的值
effect(() => {console.log(state.count);
});//修改state.count的值时,希望上面注册的副作用函数能被重新执行,从而打印出新的count值
state.count++;
如何实现依赖追踪:
a. 副作用函数的初始化
调用effect()函数时,effect函数内部会创建一个ReactiveEffect实例来封装这个副作用函数,并立即执行副作用函数。
b. 执行副作用函数前
在执行这个副作用函数之前,effect函数会将这个ReactiveEffect实例设置为activeEffect,表示当前正在执行的副作用。
c. 访问state.count
副作用函数内部访问了state.count,触发state的get拦截器。
d. get拦截器中的track调用
get拦截器调用track函数,track检查activeEffect是否存在,从而将state.count与副作用函数关联。
e. 修改state.count时的set拦截器
修改state.count触发state的set拦截器,进而触发trigger函数。
f. trigger函数中的依赖重新执行
trigger根据建立的依赖关系找到所有依赖于state.count的副作用函数并重新执行,包括我们的示例副作用函数。
1.3 实战应用
改造我们之前的vue项目里的代码,来看一下实际使用:
在页面初始化时,effect函数就会立即执行一次副作用函数,输出0
执行点击事件,state.count值变化,会触发副作用函数,输出1
1.4 activeEffect的作用:
全局追踪: activeEffect允许响应式系统知道当前执行的副作用函数,是自动依赖追踪的关键。
依赖收集: 当响应式数据被访问时,通过activeEffect将数据与副作用函数关联起来。
更新触发: 响应式数据变化时,通过收集的依赖信息找到并执行相关副作用函数。
2. 理解ReactiveEffect
2.1 定义
ReactiveEffect类封装副作用函数及其行为,代理副作用函数的执行来跟踪依赖,并在依赖数据变化时触发更新。
2.2 源码解析
export class ReactiveEffect<T = any> {//表示这个副作用是否处于活跃状态。如果为false,则副作用不会再响应依赖数据的变化。active = true//存储了这个副作用所依赖的所有数据的集合(Dep类型)。每个Dep代表一个响应式数据的依赖关系。deps: Dep[] = []/*** 某些属性或方法可以在ReactiveEffect类的实例被创建后添加或修改,computed属性就是一个例子。* 可选属性,这个属性用于指示副作用是否与计算属性相关联,可以在创建ReactiveEffect实例之后附加上去* @internal - @internal标记意味着这部分内容主要供框架内部使用,并非设计为库或框架的公开API的一部分*/computed?: ComputedRefImpl<T>/*** @internal* 可选属性,表示是否允许这个副作用递归地调用自身*/allowRecurse?: boolean//可选回调函数,当这个副作用被停止时调用onStop?: () => void// dev only:仅在开发模式下使用的回调函数,用于调试跟踪onTrack?: (event: DebuggerEvent) => void// dev only:仅在开发模式下使用的回调函数,用于触发更新onTrigger?: (event: DebuggerEvent) => void//_dirtyLevel等内部属性: 用于内部状态管理,比如判断副作用的脏检查级别等/*** @internal*/_dirtyLevel = DirtyLevels.Dirty/*** @internal*/_trackId = 0/*** @internal*/_runnings = 0/*** @internal*/_shouldSchedule = false/*** @internal*/_depsLength = 0/*** 构造函数* fn:副作用函数* trigger:触发函数(内部使用,通常为NOOP,即空操作)* scheduler:可选的调度器函数* scope:可选的作用域*/constructor(public fn: () => T,public trigger: () => void,public scheduler?: EffectScheduler,scope?: EffectScope,) {recordEffectScope(this, scope)}/*** dirty属性的get方法在ReactiveEffect类中是用来确定副作用函数是否需要被重新执行的。这个机制主要用于优化计算属性和其他依赖缓存的场景*/public get dirty() {//检查_dirtyLevel:检查当前副作用的_dirtyLevel(脏检查级别)if (this._dirtyLevel === DirtyLevels.MaybeDirty_ComputedSideEffect ||this._dirtyLevel === DirtyLevels.MaybeDirty) {//查询脏数据:为了确定是否真的需要重新计算,会将_dirtyLevel设置为QueryingDirty,this._dirtyLevel = DirtyLevels.QueryingDirty//并暂时停止依赖追踪(以避免在这个过程中不必要地收集新的依赖)pauseTracking()/*** 检查计算属性:遍历所有已注册的依赖(这些依赖代表副作用函数所依赖的数据)。*/for (let i = 0; i < this._depsLength; i++) {const dep = this.deps[i]//如果其中的依赖是计算属性(dep.computed),则会尝试触发这些计算属性的重新计算(通过triggerComputed函数)。if (dep.computed) {triggerComputed(dep.computed)//如果在这个过程中发现_dirtyLevel变为Dirty,表示确实有数据变化,需要重新计算副作用函数,那么循环就会提前结束if (this._dirtyLevel >= DirtyLevels.Dirty) {break}}}/*** 重置脏检查级别:如果遍历完所有依赖后_dirtyLevel仍然是QueryingDirty,* 表示没有发现需要更新的数据,那么将_dirtyLevel设置为NotDirty,意味着不需要重新执行副作用函数。*/if (this._dirtyLevel === DirtyLevels.QueryingDirty) {this._dirtyLevel = DirtyLevels.NotDirty}//最后,恢复依赖追踪resetTracking()}//返回值:最后,通过检查_dirtyLevel是否大于等于Dirty来决定是否标记为"脏",如果是,则表示需要重新执行副作用函数return this._dirtyLevel >= DirtyLevels.Dirty}public set dirty(v) {this._dirtyLevel = v ? DirtyLevels.Dirty : DirtyLevels.NotDirty}/*** 执行副作用函数* 在执行之前,会设置全局的activeEffect为当前实例,以便在副作用函数执行期间能够收集依赖。* 执行完成后,恢复activeEffect和shouldTrack的状态。* 如果副作用当前不处于活跃状态,直接执行副作用函数而不进行依赖收集*/run() {this._dirtyLevel = DirtyLevels.NotDirtyif (!this.active) {return this.fn()}let lastShouldTrack = shouldTracklet lastEffect = activeEffecttry {//shouldTrack设置为true,允许依赖收集shouldTrack = true/*** this引用的是ReactiveEffect类的当前实例* 将全局的activeEffect变量设置为当前的副作用实例*/activeEffect = this/*** _runnings属性记录了当前副作用函数被执行的次数* 这个计数器主要用于内部管理,确保副作用的正确执行和清理*/this._runnings++preCleanupEffect(this)return this.fn()} finally {postCleanupEffect(this)this._runnings--activeEffect = lastEffectshouldTrack = lastShouldTrack}}/*** 停止这个副作用响应其依赖数据的变化。在停止前后,会执行一些清理操作,并调用onStop回调(如果有的话)*/stop() {if (this.active) {preCleanupEffect(this)postCleanupEffect(this)this.onStop?.()this.active = false}}
}
2.3 重要属性解释
active: 控制副作用是否响应依赖数据的变化。
deps: 存储副作用所依赖的数据集合。
dirty: 脏检查机制优化计算属性更新。
3. 理解effect函数
3.1 定义
在Vue的响应式系统中,effect函数用于注册一个副作用函数(effect function),这个副作用函数可以自动响应其内部使用的响应式数据的变化。简单来说,就是当我们使用reactive或ref创建的响应式数据在这个副作用函数内被访问时,Vue会记住这个访问行为,并在数据变化时重新执行这个副作用函数。
3.2 源码解析
/*** fn:要注册为副作用的函数,当响应式数据变化时,这个函数会被重新执行。* options:可选参数,用于控制副作用的行为。常见的选项包括:* - lazy:如果为true,则副作用函数不会立即执行,直到手动调用返回的runner函数。* - scheduler:自定义的调度函数,用于控制副作用函数的重新执行时机。* - onStop:当调用stop函数停止副作用时执行的回调函数。*/
export function effect<T = any>(fn: () => T,options?: ReactiveEffectOptions,
): ReactiveEffectRunner {// 如果fn已经是一个effect函数,则获取其原始函数进行重新包装if ((fn as ReactiveEffectRunner).effect instanceof ReactiveEffect) {fn = (fn as ReactiveEffectRunner).effect.fn}// 创建一个ReactiveEffect实例,封装副作用函数fnconst _effect = new ReactiveEffect(fn, NOOP, () => {if (_effect.dirty) {_effect.run()}})// 应用传入的options配置到_effect实例上if (options) {extend(_effect, options)if (options.scope) recordEffectScope(_effect, options.scope)}// 如果不是懒执行(lazy为false),则立即执行一次副作用函数if (!options || !options.lazy) {_effect.run()}// 返回一个可以控制副作用执行的runner函数,并附加effect实例const runner = _effect.run.bind(_effect) as ReactiveEffectRunnerrunner.effect = _effectreturn runner
}
3.3 工作原理
3.3.1 封装副作用函数
通过创建一个ReactiveEffect实例来封装传入的fn函数。这个封装包括对副作用函数的执行上下文管理,以及依赖追踪和触发逻辑的处理。
3.3.2 自动执行和响应
默认情况下,封装的副作用函数会立即执行一次。在执行过程中,ReactiveEffect会设置activeEffect指向当前的副作用实例,这样任何被访问的响应式数据都会将当前的副作用函数收集为依赖。当响应式数据变化时,所有收集的依赖会被重新执行,即重新执行副作用函数。
3.3.3 控制执行
effect函数返回一个runner函数,通过这个runner函数可以手动控制副作用的执行,特别是在配置了lazy选项时。同时,runner函数上附带的effect属性允许直接访问到内部的ReactiveEffect实例,进一步控制或查询副作用的状态。
3.4 runner解析
const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
runner.effect = _effect
这段代码的目的是创建一个可以被直接调用的函数(runner),用来控制副作用(effect)的执行,并且让这个runner函数具有一些额外的属性和能力。下面详细解释这段代码的含义和作用:
简化API:
通过返回一个函数(runner),使用者可以直接执行这个函数来触发副作用,而不需要从_effect实例中调用run方法。这样的API更加简洁直观。
绑定上下文:_effect.run.bind(_effect):
使用.bind(_effect)是为了确保在run方法内部,this关键字指向的是_effect实例本身,而不是其他的上下文。这样,无论runner函数在哪里被调用,它内部通过this访问的都是正确的ReactiveEffect实例。
类型安全:as ReactiveEffectRunner:
这是TypeScript的类型断言,用来指明runner函数是ReactiveEffectRunner类型。ReactiveEffectRunner类型除了是一个可调用的函数之外,还额外附带了一个effect属性。这样做的目的是为了让TypeScript的类型系统知道runner不仅仅是一个普通的函数,还是一个特殊的对象,拥有effect属性。
保留引用:runner.effect = _effect:
这行代码给runner函数对象添加了一个名为effect的属性,并将这个属性的值设置为_effect实例。这样做的目的是让外部代码能够通过runner函数直接访问到内部的ReactiveEffect实例。这在某些场景下非常有用,比如需要停止或查询副作用的状态时,可以通过runner.effect来操作。
综上所述,这段代码创建了一个runner函数,这个函数不仅可以被调用来执行副作用,还允许外部代码通过runner.effect直接访问和控制副作用实例。这是Vue响应式系统灵活且强大的设计之一。
4. 小结
再看我们1.2的示例来回顾一下,这里的每一步都是响应式系统核心机制的重要组成部分:
4.1 副作用函数的初始化
使用effect(fn)时,Vue会创建一个ReactiveEffect实例,这个实例包装了用户定义的副作用函数fn。这时,全局的activeEffect被设置为这个实例,并且shouldTrack变为true,允许依赖收集。
4.2 依赖收集(Tracking)
在副作用函数执行过程中,任何被访问的响应式对象属性(例如state.count)的访问都会被相应对象的get拦截器捕获。get拦截器会调用track函数,将当前的activeEffect(副作用函数)与这个属性关联起来,并在targetMap中记录这个依赖关系。
4.3 触发更新(Triggering)
当响应式对象的属性被修改时(如state.count被赋予一个新值),这个操作会被属性所属对象的set拦截器捕获。set拦截器随后调用trigger函数,查找所有依赖于被修改属性的副作用函数,并触发它们重新执行。
4.4 重新执行副作用函数
trigger函数根据在targetMap中记录的依赖关系找到所有依赖的副作用函数,并重新执行它们。这样,任何基于这个响应式数据的计算或UI更新都会被自动进行。
相关文章:
【Vue3源码学习】— CH2.6 effect.ts:详解
effect.ts:详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…...
C语言:文件操作(一)
目录 前言 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 结(一) 前言 本篇文章将介绍C语言的文件操作,在后面的内容讲到:为什么使用文…...
集中进行一系列处理——函数
需要多次执行相同的处理,除了编写循环语句之外,还可以集中起来对它进行定义。 对一系列处理进行定义的做法被称为函数,步骤,子程序。 对函数进行定一后,只需要调用该函数就可以了。如果需要对处理的内容进行修正&…...
git diff
1. 如何将库文件的变化生成到patch中 git diff --binary commit1 commit2 > test.patch 打patch: git apply test.patch 2. 如何消除trailing whitespace 问题 git diff --ignore-space-at-eol commit1 commit2 > test.patch 打patch: git ap…...
新手使用GIT上传本地项目到Github(个人笔记)
亲测下面的文章很有用处。 1. 初次使用git上传代码到github远程仓库 - 知乎 (zhihu.com) 2. 使用Git时出现refusing to merge unrelated histories的解决办法 - 知乎...
结合《人力资源管理系统》的Java基础题
1.编写一个Java方法,接受一个整数数组作为参数,返回该数组中工资高于平均工资的员工数量。假设数组中的每个元素都代表一个员工的工资。 2.设计一个Java方法,接受一个字符串数组和一个关键字作为参数,返回包含该关键字的姓名的员…...
PostgreSQL备份还原数据库
1.切换PostgreSQL bin目录 配置Postgresql环境变量后可以不用切换 pg_dump 、psql都在postgresql bin目录下,所以需要切换到bin目录执行命令 2.备份数据库 方式一 语法 pg_dump -h <ip> -U <pg_username> -p <port> -d <databaseName>…...
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用 在数据库管理中,读写分离是一种常见的性能优化方法,它通过将读操作和写操作分发到不同的服务器或数据库实例上,来减轻单个数据库的负载&#x…...
pytest中文使用文档----10skip和xfail标记
1. 跳过测试用例的执行 1.1. pytest.mark.skip装饰器1.2. pytest.skip方法1.3. pytest.mark.skipif装饰器1.4. pytest.importorskip方法1.5. 跳过测试类1.6. 跳过测试模块1.7. 跳过指定文件或目录1.8. 总结 2. 标记用例为预期失败的 2.1. 去使能xfail标记 3. 结合pytest.param方…...
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring MVC】快速学习使用Spring MVC的注解及三层架构 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 Spring Web MVC一: 什么是Spring Web MVC࿱…...
Python(乱学)
字典在转化为其他类型时,会出现是否舍弃value的操作,只有在转化为字符串的时候才不会舍弃value 注释的快捷键是ctrl/ 字符串无法与整数,浮点数,等用加号完成拼接 5不入??? 还有一种格式化的方法…...
OpenHarmony实战:轻量级系统之子系统移植概述
OpenHarmony系统功能按照“系统 > 子系统 > 部件”逐级展开,支持根据实际需求裁剪某些非必要的部件,本文以部分子系统、部件为例进行介绍。若想使用OpenHarmony系统的能力,需要对相应子系统进行适配。 OpenHarmony芯片适配常见子系统列…...
Neo4j基础知识
图数据库简介 图数据库是基于数学里图论的思想和算法而实现的高效处理复杂关系网络的新型数据库系统。它善于高效处理大量的、复杂的、互连的、多变的数据。其计算效率远远高于传统的关系型数据库。 在图形数据库当中,每个节点代表一个对象,节点之间的…...
HTTP/1.1 特性(计算机网络)
HTTP/1.1 的优点有哪些? 「简单、灵活和易于扩展、应用广泛和跨平台」 1. 简单 HTTP 基本的报文格式就是 header body,头部信息也是 key-value 简单文本的形式,易于理解。 2. 灵活和易于扩展 HTTP 协议里的各类请求方法、URI/URL、状态码…...
每日一题————P5725 【深基4.习8】求三角形
题目: 题目乍一看非常的简单,属于初学者都会的问题——————————但是实际上呢,有一些小小的坑在里面。 就是三角形的打印。 平常我们在写代码的时候,遇到打印三角形的题,一般简简单单两个for循环搞定 #inclu…...
第三题:时间加法
题目描述 现在时间是 a 点 b 分,请问 t 分钟后,是几点几分? 输入描述 输入的第一行包含一个整数 a。 第二行包含一个整数 b。 第三行包含一个整数 t。 其中,0≤a≤23,0≤b≤59,0≤t, 分钟后还是在当天。 输出描…...
【RAG】内部外挂知识库搭建-本地GPT
大半年的项目告一段落了,现在自己找找感兴趣的东西学习下,看看可不可以搞出个效果不错的local GPT,自研下大模型吧 RAG是什么? 检索增强生成(RAG)是指对大型语言模型输出进行优化,使其能够在生成响应之前引用训练数据来…...
MySQL——锁
全局锁 全局锁是一种数据库锁定机制,它可以锁定整个数据库,阻止其他会话对数据库的读写操作。在MySQL中,全局锁定可以使用FLUSH TABLES WITH READ LOCK命令来实现。执行这个命令后,MySQL将获取一个全局读锁,直到当前会…...
C++(12): std::mutex及其高级变种的使用
1. 简述 在多线程或其他许多场景下,同时对一个变量或一段资源进行读写操作是一个比较常见的过程,保证数据的一致性和防止竞态条件至关重要。 C的标准库中为我们提供了使用的互斥及锁对象,帮助我们实现资源的互斥操作。 2. std::mutex及其衍…...
基于ROS软路由的百元硬件升级方案实现突破千兆宽带
前言 很多用户得利于FTTR光网络不断推广,家用宽带带宽已经实现千兆速率的突破。而现在很多ISP运营商已经在多个城市率先推出2000M光宽带。这种情况下,要想将自家宽带的带宽能够充分发挥利用,就需要对原有的千兆设备进行升级来满足突破千兆的…...
OpenHarmony实战开发-分布式关系型数据库
介绍 本示例使用ohos.data.relationalStore 接口和ohos.distributedDeviceManager 接口展示了在eTS中分布式关系型数据库的使用,在增、删、改、查的基本操作外,还包括分布式数据库的数据同步同能。 效果预览 使用说明: 1.启动应用后点击“”按钮可以添…...
图片标注编辑平台搭建系列教程(6)——fabric渲染原理
原理 fabric的渲染步骤大致如下: 渲染前都设置背景图然后调用ctx.save(),存储画布的绘制状态参数然后调用每个object自身的渲染方法最后调用ctx.restore(),恢复画布的保存状态后处理,例如控制框的渲染等 值得注意的是࿰…...
Qt中QIcon图标设置(标题、菜单栏、工具栏、状态栏图标)
1 exe程序图标概述 在 Windows 操作系统中,程序图标一般会涉及三个地方; (1) 可执行程序(以及对应的快捷方式)的图标 (2) 程序界面标题栏图标 (3)程序在任务…...
C语言程序10题
第101题 (10.0分) 难度:易 第2章 /*------------------------------------------------------- 【程序填空】 --------------------------------------------------------- 功能:计算平均成绩并统计90分以上人数。 --…...
定时器-间歇函数
1.开启定时器 setInterval(function (){console.log(一秒执行一次)},1000) function fn(){console.log(一秒执行一次) } setInterval(fn,1000) //调用有名的函数,只写函数名 1.函数名字不需要加小括号 2.定时器返回是一个id数字 每个定时器的序号是不一样的 2.关…...
Ajax-XMLHttpRequest基本使用
一、Ajax的原理 就是XMLHttpRequest对象。 二、为什么学习XHR? 有更多与服务器数据通信方式,了解Ajax内部。 三、XHR使用步骤 1.创建XHR对象 2.调用open方法,设置url和请求方法 3.监听loadend事件,接受结果 4.调用send方法…...
门控循环单元(GRU)
概述 门控循环单元(Gated Recurrent Unit, GRU)由Junyoung Chung等人于2014年提出,原论文为《Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling》。GRU是循环神经网络(Recurrent Neural Network, …...
789. 数的范围 (二分学习)左端大右,右端小左
题目链接https://www.acwing.com/file_system/file/content/whole/index/content/4317/ 当求左端点时,条件是a【mid】大于等于x,并把右端点缩小。 当求右端点时,条件是a【mid】小于等于x,并把左端点扩大。 1.确定一个区间&…...
docker logs 查找日志常用命令
docker logs 是什么 docker logs 是 Docker 命令行工具提供的一个命令,用于查看容器的日志输出。它可以显示容器在运行过程中生成的标准输出(stdout)和标准错误输出(stderr),帮助用户诊断容器的行为和排查…...
百卓Smart管理平台 importexport.php SQL注入漏洞复现(CVE-2024-27718)
0x01 产品简介 百卓Smart管理平台是北京百卓网络技术有限公司(以下简称百卓网络)的一款安全网关产品,是一家致力于构建下一代安全互联网的高科技企业。 0x02 漏洞概述 百卓Smart管理平台 importexport.php 接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数据…...
网站的维护怎么做/百度怎么发布自己的广告
我安装了32位的office 然后今天突发奇想 安装了一个64位的 visio ,之后看到有人在网上发文章 如何解决viso2013无法安装64位版本的Office https://jingyan.baidu.com/article/a65957f4db6ae124e67f9b9b.html 我就按照上面的操作进行了一番神操作 我在没有备份的情…...
政府网站的集约化建设 黄月/网络推广网络营销外包
EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流。 有五种不同的事件机制:EventListenerTouch 响应触控事件EventListenerKeyboard 响应键盘事件EventListen…...
网站建设规划方案ppt/抖音自动推广引流app
/ 网站根路径 ./ 当前路径 ../ 上一级路径 ../../ 上两级路径 例如:本地静态网站 index页面地址 127.0.0.1/bootstrap_test/index.html在这里页面里面引入css和js路径应该怎么写呢? 1、 <link href"css/bootstrap.min.css" rel"style…...
wordpress自动更新电视剧/网站推广四个阶段
这一题的思路想对了,就是middle justify的时候,当一行空格不均匀分配的处理没想清楚。 不知道这题考的点在哪里 class Solution {public List<String> fullJustify(String[] words, int maxWidth) {//res保存每一个string里的单词个数List<Int…...
怎么在一起做网站上拿货/竞价托管是啥意思
我一直坚持在Linux下钻研计算机软件的相关知识,三个半月前学完了《数据库系统概论》这本书。在学习中我使用了MySQL作为练兵场,但当我学到书的后半部分的时候,发现MySQL有一些问题: 1、MySQL没有角色权限控制功能,也就…...
免费网站建设市场/怎么做推广让别人主动加我
计算机二级access题库答案在文末1.在Access数据库中,一个关系就是一个【 A】。A)二维表 B)记录C)字段 D)数据库 综合数据2. 设有部门和员工两个实体,每个员工只能属于一个部门,一个部门可以有多名员工,则部门与…...