Vue3 API

📍前言 最近在一次理解vue项目的代码时,发现周一对好多API都不太熟悉。这间接导致的问题是,代码理解速度要比平常要慢很多。于是乎,赶忙把vue API的学习提上了日程。 在下面的文章中,将地板式地扫盲vue3文档中API模块的所有内容,融入周一的理解进行深入介绍。下面就来一起看看吧~🍬 一、🖇框架搭建 1、关于文档 首先附上官方文档的具体材料:cn.vuejs.org/api/ 2、VUE3 API整体盘点 在vue3的全新API中,有部分在vue2的基础上沿用了。还有另外一部分,是vue3所新增加的。我们先来看vue3 API文档主要包含哪些内容? vue3 API主要包含以下六个部分: 全局API —— 全局会用到的API 组合式API —— vue3所拥有的组合式API 选项式API —— vue2所拥有的选项式API 内置内容 —— 指令、组件、特殊元素和特殊属性 单文件组件 —— 语法定义、 进阶API —— 渲染函数、服务端渲染、TS工具类型和自定义渲染 下面将依据上面提到的六大点内容,来进行相应的剖析和讲解。 二、🎨全局API vue3的全局API包含两个部分:应用实例和通用API。那它们各自都有哪些内容呢? 1、应用实例 2、通用API 三、🚲组合式API 谈到vue3 ,相信大家最为熟悉的就是 composition API 了,也就是 组合式 API 。那么,vue3 的 组合式 API 都给我们带来了什么呢? 1、setup 2、响应式:核心 3、响应式:工具函数 4、响应式:进阶 5、生命周期钩子 6、依赖注入 四、🌠选项式API 选项式API 即 options API 。可能有的小伙伴会觉得它在 vue2 项目下会更为常见一些。但在 vue3 项目中,也是有一些 选项式API 值得我们去挖掘的。那都有哪些内容呢,我们来一探究竟。 ...

October 5, 2024

RunLoop

RunLoop 是 iOS/macOS 中用于管理线程的事件循环机制。它的核心作用是让线程在有任务时处理任务,没有任务时进入休眠状态,从而避免线程退出并节省 CPU 资源。 简单来说,RunLoop 就是一个 do-while 循环: // 伪代码 void CFRunLoopRun() { do { // 处理各种事件源 // 如果没有事件,线程休眠 // 有事件时被唤醒处理 } while (running); } RunLoop 与线程的关系 每个线程都有唯一对应的 RunLoop 对象 主线程和子线程的 RunLoop 都采用懒加载机制,在第一次获取时才创建 主线程的 RunLoop 由 UIApplicationMain 内部首次获取并启动(调用链:UIApplicationMain → GSEventRunModal → CFRunLoopRunSpecific) RunLoop 与线程是一一对应的,存储在一个全局字典(__CFRunLoops)中 // 获取当前线程的 RunLoop CFRunLoopRef runLoop = CFRunLoopGetCurrent(); NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; // 获取主线程的 RunLoop CFRunLoopRef mainRunLoop = CFRunLoopGetMain(); NSRunLoop *mainRunLoop = [NSRunLoop mainRunLoop]; RunLoop 的核心组成 RunLoop 包含以下几个核心概念: 1. RunLoop 对象(CFRunLoopRef) RunLoop 对象本身,管理整个事件循环。在代码层面对应 CFRunLoopRef 类型。 ...

May 27, 2026

数组常用方法

数组是 js 中最常用到的数据集合,其内置的方法有很多,熟练掌握这些方法,可以有效的提高我们的工作效率,同时对我们的代码质量也是有很大影响。 一、创建数组 1.使用数组字面量表示法 var arr4 = []; //创建一个空数组 var arr5 = [20]; // 创建一个包含1项数据为20的数组 var arr6 = ["lily","lucy","Tom"]; // 创建一个包含3个字符串的数组 2.使用 Array 构造函数 无参构造 var arr1 = new Array(); //创建一个空数组 带参构造 如果只传一个数值参数,则表示创建一个初始长度为指定数值的空数组 var arr2 = new Array(20); // 创建一个包含20项的数组 如果传入一个非数值的参数或者参数个数大于 1,则表示创建一个包含指定元素的数组 var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组 var array4 = new Array('23'); // ["23"] 3.Array.of 方法创建数组(es6 新增) ES6 为数组新增创建方法的目的之一,是帮助开发者在使用 Array 构造器时避开 js 语言的一个怪异点。 Array.of()方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型。 let arr = Array.of(1, 2); console.log(arr.length);//2 let arr1 = Array.of(3); console.log(arr1.length);//1 console.log(arr1[0]);//3 let arr2 = Array.of('2'); console.log(arr2.length);//1 console.log(arr2[0]);//'2' 4.Array.from 方法创建数组(es6 新增) 在 js 中将非数组对象转换为真正的数组是非常麻烦的。在 ES6 中,将可迭代对象或者类数组对象作为第一个参数传入,Array.from()就能返回一个数组。 function arga(...args) { //...args剩余参数数组,由传递给函数的实际参数提供 let arg = Array.from(args); console.log(arg); } arga('arr1', 26, 'from'); // ['arr1',26,'from'] 映射转换 如果你想实行进一步的数组转换,你可以向 Array.from()方法传递一个映射用的函数作为第二个参数。此函数会将数组对象的每一个值转换为目标形式,并将其存储在目标数组的对应位置上。 ...

November 8, 2024

CSR,SSR和SSG

SPA、MPA、SSR 和 CSR 这几个词可能在你的工作生涯中经常出现,网上相关文章也很多。如果你对这些概念感到模糊或完全不了解,希望本文能帮助你理解这些渲染模式。 SPA 与 MPA MPA MPA(multiple page application) 称为多页应用, 指的是有多个页面的应用,从技术手段上来讲,你可以这么粗略地理解。 首屏速度快:各个页面相互独立,需要单独维护多个 html 页面,每个请求都直接返回 html。 切换页面比较慢:基于原生浏览器的文档跳转(navigating across documents)。因此每一次的页面更新都是一次页面重载,这将带来巨大的重启性能消耗。 对 SEO 友好:页面在初始时,就具有全部的页面内容而非 「无状态」,从而达到更好的收录效果。 SPA SPA(single page application)称为单页应用。通过 js 去感知到 url 的变化,动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上。此时的路由不是后端来做了,而是前端来做,动态显示需要的组件。 页面切换速度快:路由跳转是基于特定的实现(如 vue-router,react-router 等前端路由),而非原生浏览器的文档跳转,避免了不必要的整个页面重载。 前后端分离:基于前端路由,SPA 与应用后端解耦,使得前端不再依赖于后端的路由分配。 首屏时间慢:首屏除了 html 还要额外请求并执行 js 文件,通过 js 在空页面上渲染首屏。 SEO 不友好:内容都是靠 js 渲染生成出来的,但搜索引擎并不识别这部分内容,导致 SEO 效果差 CSR(Client Side Rendering) CSR(客户端渲染)是一种在浏览器上执行 JavaScript 以生成 DOM 并显示内容的渲染方法。CSR 更贴近现代前端开发,我们通常使用的 Vue 和 React 默认使用 CSR。其大致流程如下: 浏览器向前端服务器请求 html 和 js html 页面为空,初始加载不显示任何内容,通过执行 js 渲染内容 通过后端暴露的 API 进行交互 对于典型的 CSR 应用程序,浏览器仅接收一个用作应用程序容器的 HTML 页面,因此也称为单页应用,所以 CSR 的特点与之前提到的 SPA 类似。 ...

November 5, 2024

架构

前言 在项目中经常存在如下问题: 1.模块拆分不合理 2.变量和函数命名不知所云 3.缺少注释或者是写了一堆描述不清的内容 4.重复的代码遍布各个角落等 因为这些不良的编程习惯,导致了项目越来越难以维护,程序性能越来越低,大大降低了日常的工作效率以及提高了公司的开发成本。 下面就以CSS在Vue3项目中的架构为切入点,通过减少CSS代码的冗余度和增强CSS代码的维护性、扩展性来提高我们的编程能力和项目架构能力。 CSS的设计模式 在学习CSS架构之前,我们先简单看一下常见的5种CSS设计模式,这些设计模式都为我们的CSS架构提供了一定的开发思路。 1.OOCSS模式 OOCSS(Object-Oriented CSS)字面意思是面向对象的CSS,在开发中它有如下的规范约定 减少对 HTML 结构的依赖 # bad # 1.匹配效率低,影响css性能 # 2.和html耦合度高,维护性和扩展性低 .container-list ul li a {} <div class="container-list"> <ul> <li> <a>...</a> </li> </ul> </div> # good .container-list .list-item {} <div class="container-list"> <ul> <li> <a class="list-item">...</a> </li> </ul> </div> 增加样式的复用性 .label { # 公共代码 } .label-danger { # 特定代码 } .label-info { # 特定代码 } <div> <p class="label label-danger"></p> <p class="label label-info"></p> </div> 2.BEM模式 BEM 是进阶版的OOCSS,是一个分层系统,它把我们的网站分为三层,这三层正好对应着 BEM 三个英文单词的简写 block, element, modifier,分为为 块层、元素层、修饰符层。 ...

October 10, 2024

响应式原理

什么是响应式系统 在 Vue 中,数据驱动视图是一个非常重要的概念。当数据发生变化时,视图会自动更新,这是因为 Vue 实现了一个响应式系统,通过追踪依赖关系来自动更新视图。 简单来说,响应式系统就是 Vue 能够监听数据变化,并在变化时自动更新 DOM 的核心机制。在 Vue3 中,响应式系统的改进使得响应式数据可以更加高效地更新视图,同时也提升了开发体验和性能。 Vue2 的响应式原理 在 Vue2 中,响应式原理是通过 Object.defineProperty 来实现的。Vue 会在数据对象上定义 getter 和 setter,来实现数据变化时更新视图的功能。 举个例子,当一个数据对象被定义为响应式时,我们可以通过访问这个对象的属性来触发 get 操作。具体实现如下: Object.defineProperty(obj, 'foo', { get: function() { console.log('get foo') return obj._foo }, set: function(newVal) { console.log('set foo') obj._foo = newVal } }) 在上面的代码中,我们通过 Object.defineProperty 方法来监听对象上的属性 foo,当访问 foo 属性时,会触发 get 操作,并输出日志。同理,当给 foo 属性赋值时,会触发 set 操作,并输出日志。 在 Vue2 中,我们可以通过使用上面的方法来将数据对象中的所有属性转化成响应式的,以实现数据变化时更新视图的功能。 Vue3 的响应式原理 在 Vue3 中,响应式原理的实现方式和 Vue2 相比,有了相当大的变化。Vue3 直接使用了 ES6 Proxy 对象来拦截对对象的访问操作。Proxy 可以监听到对对象进行的访问、赋值等操作,并在这些操作发生时通知相关依赖以维护响应式系统的更新。 ...

October 5, 2024

Runtime

什么是 Runtime Runtime 是 Objective-C 的运行时系统,是一套底层的 C 语言 API。Objective-C 是一门动态语言,很多操作都是在运行时而非编译时决定的,这一切都依赖于 Runtime。 Runtime 提供的核心能力: 消息发送与转发 方法交换(Method Swizzling) 关联对象(Associated Objects) 动态创建类和对象 动态添加和修改方法、属性 关于对象、类、isa 指针等底层数据结构的详细介绍,请参考 Objective-C底层原理-NSObject。本文专注于 Runtime 的动态能力和实际应用。 消息发送机制 Objective-C 的消息发送机制是其动态性的核心体现。与 Swift 支持静态派发不同,Objective-C 的方法调用都是动态消息派发。更多关于两者的对比,请参考 Objective-C与Swift区别。 objc_msgSend Objective-C 的方法调用本质上是消息发送,编译器会将方法调用转换为 objc_msgSend 函数: // 源代码 [obj doSomething]; // 编译后 objc_msgSend(obj, @selector(doSomething)); 消息发送流程 1. 检查 receiver 是否为 nil,如果是则直接返回 2. 通过 isa 找到 receiver 的类对象 3. 在类对象的方法缓存(cache_t)中查找方法 4. 如果缓存命中,直接调用方法实现(IMP) 5. 如果缓存未命中,在类对象的方法列表中查找 6. 如果找到,缓存方法并调用 7. 如果未找到,沿着 superclass 链向上查找 8. 如果最终未找到,进入消息转发流程 方法缓存 为了提高消息发送效率,Runtime 在类对象中使用哈希表缓存最近调用的方法: ...

May 2, 2026

浏览器解析 HTML 文件

1. 什么是浏览器解析和渲染HTML 一句话概括:将html代码转换成页面上显示的内容。 表1:形象展示将HTML转换成页面上显示的内容 2. 浏览器解析和渲染HTML过程? 那么浏览器拿到HTML代码后是如何把其转换成页面上显示的内容的? 2.1 宏观描述执行过程 2.1.1 解析和渲染 首先我们来看两个概念,解析和渲染,确切来说是DOM解析和DOM渲染。 DOM解析: 生成DOM tree的过程。就是把你所写的各种html标签,生成一个DOM tree,可以认为就是生成了一个最原始的页面,一点样式都没有,毫无CSS修饰。 DOM渲染: 将DOM tree与css样式结合,生成Render tree,并将其呈现在浏览器页面上。浏览器会把本身默认的样式+用户自己写得样式整合到一起,形成一个CSS tree,而DOM渲染就是指DOM tree 和CSS tree 结合到一起,生成一个Render tree,呈现出一个带有样式的页面。 这里需要注意,DOM解析和DOM渲染由两个不同的线程来完成的,简单说就是二者可以并行进行。 DOM解析通常是由浏览器的主线程来完成的。DOM渲染是由浏览器的渲染线程来完成的。 分离解析和渲染的这种设计使得浏览器能够在解析 HTML 文档的同时将页面渲染到屏幕上,这样用户就能够更快地看到完整的页面了。 2.1.2 宏观描述执行过程 补充了解析和渲染的概念,我们来看看浏览器具体是如何把其转换成页面上显示的内容的。其过程大致分为下图的四步。 图1:浏览器解析和渲染HTML的过程 第一步:将载入的HTML文件解析成DOM树(DOM tree),并且将各个标记标识解析成DOM树的各个节点;在解析HTML的同时会将CSS样式解析成CSS规则(CSS rules)。 第二步:将解析成的DOM树和CSS规则进行关联生成渲染树(Render tree)。 第三步:进入布局阶段,为DOM树的每个节点分配在屏幕上出现的确切坐标(这一阶段还是渲染树) 第四步:进入绘制阶段,在这里渲染引擎的工作就结束了,接下来就给用户界面后端(UI Backend)对渲染树的每个节点进行绘制,呈现出页面效果。 2.2 细化执行过程 2.2.1 顺序执行 dom解析过程是从上向下,顺序执行的。顺序执行的意思是一行一行的执行,上一行执行完再执行下一行。 <h1>1<h1> <h1>2<h1> <h1>3<h1> <script></script> <style></style> <!-- 先1,再2,再3,按顺序解析。 --> 2.2.2 渐进式 浏览器是渐进式渲染,即边解析边渲染。通俗的说就是,这一行代码解析完,就可以在浏览器的页面渲染展示出来。因为浏览器的解析和渲染由两个不同线程来完成,所以可以实现边解析边渲染。 <h1>1</h1> <script>debugger</script> <h1>2</h1> <script>debugger</script> <h1>3</h1> <!-- 先解析渲染出1,再debugger;再解析渲染出2,再debugger;最后解析渲染出3 --> 2.3 问题:css、js会阻塞解析和渲染吗? 这部分内容可参考这篇掘金内容,内含测试代码:关于 JS 与 CSS 是否阻塞 DOM 的渲染和解析 - 掘金 ...

November 5, 2024

视觉格式化模型

大部分 Web 开发者都知道 CSS 中有一个盒模型,但很少有人知道在 CSS 的世界中还有另一个模型,他就是 CSS 的视觉格式化模型。 CSS 视觉格式化模型(英文称之Visual Formatting Model)。该模型主要是用来处理在视觉媒体上显示文档时使用的计算规则。仅从这一句话来描述,估计很多同学都会感到困惑,视觉格式化模型到底是什么鬼?大家先不用急着知道视觉格式化模型是什么,只需要知道它是 CSS 中很重要的一部分,如果理解了该部分所涉及到的知识点,将有助于你更好的理解和学习 CSS,特别是 Web 布局 什么是视觉格式化模型 在盒模型中我们了解到,在 CSS 的世界中,任何一个元素都是一个盒子,它具有一个专业术语,即盒模型。而视觉格式化模型会根据 CSS 盒模型将文档中的元素转换为一个个盒子。看到这里,很多同学可能更会感到困惑,“任何元素都是一个盒子,视觉格式化模型将元素转换为盒子,那这盒子是不是都是一样的盒子呢”? 首先要声明一点:视觉格式化模型和CSS盒模型不是同一个东西! 简单点说呢。Web 页面(文档树)是由很一个个盒子组成(因为任何元素都可以被视为是一个盒子),而视觉格式化模型却是一套规则,用来计算元素转换为盒子的规则。而页面的布局都由这些盒子的所处的各处位置组合而成。那么理解了元素怎么转成盒子的规则,就理解了 Web 页面是怎么布局。而每个盒子的布局主要由以下几个因素决定: 盒子的尺寸:精确指定、由约束条件指定或没有指定 盒子的类型:行内盒子(inline)、行内级盒子(inline-level)、原子行内级盒子(atomic inline-level)和块盒子(block) 定位方案:普通流定位、浮动定位或绝对定位 文档树中的其它元素:即当前盒子的子元素或兄弟元素 视窗尺寸与位置 所包含的图片的尺寸 其他的某些外部因素 先来看一张图,这个图是由下面的 HTML 结构构造出来的: <body> <header> <nav></nav> </header> <article> <p></p> <figure></figure> <p></p> </article> <aside></aside> <footer></footer> </body> 每个元素都是一个盒子,盒子中可以包含另一个或多个盒子。也正如上图所示,CSS 的视觉格式化模型会根据盒子的包含块(Containing Block,即包含其他盒子的块)的边界来渲染盒子。通常,盒子会创建一个包含其后代元素的包含块,但是盒子并不会被包含块限制住,盒子的布局会撑破包含块(即跑出包含块的边界),对于这种现象,在 CSS 中常被称为溢出。 溢出是一个很有意思的东东,在 Web 布局中时常会碰到,但在这一章中不做方面的阐述。 ...

October 10, 2024

watch与watchEffect

Watch 基本用法 当我们需要在数据变化时执行一些“副作用”:如更改 DOM、执行异步操作,我们可以使用 watch 函数: <script setup> import { ref, watch } from 'vue' const question = ref('') const answer = ref('This is answer. ;-)') // 侦听一个 ref watch(question, async (newQuestion, oldQuestion) => { answer.value = 'Thinking...' const res = await fetch('https://...') answer.value = (await res.json()).answer }) </script> <template> <input v-model="question" /> <p>{{ answer }}</p> </template> watch() 一共可以接受三个参数,侦听数据源、回调函数和配置选项。 侦听数据源 watch 的第一个参数可以是不同形式的“数据源”,它可以是: 一个 ref 一个计算属性 一个 getter 函数(有返回值的函数) 一个响应式对象 以上类型的值组成的数组 const x = ref(1) const y = ref(1) const doubleX = computed(() => x.value * 2) const obj = reactive({ count: 0 }) // 单个 ref watch(x, (newValue) => { console.log(`x is ${newValue}`) }) // 计算属性 watch(doubleX, (newValue) => { console.log(`doubleX is ${newValue}`) }) // getter 函数 watch( () => x.value + y.value, (sum) => { console.log(`sum of x + y is: ${sum}`) } ) // 响应式对象 watch(obj, (newValue, oldValue) => { // 在嵌套的属性变更时触发 // 注意:`newValue` 此处和 `oldValue` 是相等的 // 因为它们是同一个对象! }) // 以上类型的值组成的数组 watch([x, () => y.value], ([newX, newY]) => { console.log(`x is ${newX} and y is ${newY}`) }) 注意,你不能直接侦听响应式对象的属性值,例如: ...

October 5, 2024