This commit is contained in:
539943419 committed 2024-12-13 11:17:19 +08:00
1 parent 8d75346c80
commit 7434accb0e
7 files changed
+614 -187

No files matched your search

+3 -1
View File
@@ -1 +1,3 @@
node_modules
node_modules
test.*
.vscode
+191 -158
View File
@@ -1,194 +1,227 @@
# 与 css 相关,多学习 css
## css inset
- inset : top | right| bottom | left
- 使用例:
```css
.className {
inset: 4px 8px; /* 上下 | 左右 */
inset: 5px 15px 10px; /* 上 | 左右 | 下 */
inset: 2.4em 3em 3em 3em; /* 上 | 右 | 下 | 左 */
}
```
- 同时设置上下左右等多个属性值
- inset : top | right| bottom | left
- 使用例:
```css
.className {
inset: 4px 8px; /* 上下 | 左右 */
inset: 5px 15px 10px; /* 上 | 左右 | 下 */
inset: 2.4em 3em 3em 3em; /* 上 | 右 | 下 | 左 */
}
```
## css 过渡 transition
- 有transition-property、transition-duration、transition-timing-function 和 transition-delay这几个属性,不过一般使用时应该都是用transition合起来写。
- 使用例:
```css
.className {
/* property name | duration | timing function | delay */
transition: margin-right 4s ease-in-out 1s;
- 有 transition-property、transition-duration、transition-timing-function 和 transition-delay 这几个属性,不过一般使用时应该都是用 transition 合起来写。
- 使用例:
/* Apply to 2 properties */
transition: margin-right 4s, color 1s;
}
```
```css
.className {
/* property name | duration | timing function | delay */
transition: margin-right 4s ease-in-out 1s;
/* Apply to 2 properties */
transition: margin-right 4s, color 1s;
}
```
## css 动画 滚动条驱动
- animation-timeline
- 有时间再写
- animation-timeline
- 有时间再写
## css 动画
- 分为“定义”与“使用”两个阶段。
- “定义”阶段的 keyword 为@keyframes,例:
- 分为“定义”与“使用”两个阶段。
- “定义”阶段的 keyword 为@keyframes,例:
```scss
// 每个时间点填对应时间点的style
@keyframes animationName {
0% {
border-radius: 1px;
}
50% {
border-radius: 12px;
}
100% {
border-radius: 123px;
}
}
```
```scss
// 每个时间点填对应时间点的style
@keyframes animationName {
0% {
border-radius: 1px;
}
50% {
border-radius: 12px;
}
100% {
border-radius: 123px;
}
}
```
- “使用”阶段的 keyword 为 animation,使用 animation 绑定动画,例
```scss
div {
animation: animationName 5s;
}
```
- animation 有许多属性
- “使用”阶段的 keyword 为 animation,使用 animation 绑定动画,例
```scss
div {
animation: animationName 5s;
}
```
- animation 有许多属性
```scss
div {
// 绑定的动画名
animation-name: animationName;
// 动画执行总时长
animation-duration: 5s;
// 速度曲线。默认是 "ease"。
animation-timing-function: linear;
animation-delay: 2s;
// 播放次数,默认1
animation-iteration-count: infinite;
// 是否在下一个周期逆向播放
animation-direction: alternate;
// 是否正在播放()
animation-play-state: running;
// 简写
animation: animationName 5s linear 2s infinite alternate;
// 多个动画之间使用逗号进行隔开
animation: a1..., a2...;
}
```
```scss
div {
// 绑定的动画名
animation-name: animationName;
// 动画执行总时长
animation-duration: 5s;
// 速度曲线。默认是 "ease"。
animation-timing-function: linear;
animation-delay: 2s;
// 播放次数,默认1
animation-iteration-count: infinite;
// 是否在下一个周期逆向播放
animation-direction: alternate;
// 是否正在播放()
animation-play-state: running;
// 简写
animation: animationName 5s linear 2s infinite alternate;
// 多个动画之间使用逗号进行隔开
animation: a1..., a2...;
}
```
## before 与 after
- 伪元素,通过 content 来指定内容,before 就是在前面,after 就是在后面(哇好有道理呢)
- 用途一般是加个 icon 啥的,content 可以为 url(...)
- 不能应用在替换元素上,比如 `<img>`
- 伪元素不支持嵌套,也就是说伪元素的父元素不可以为伪元素
使用例:
- 伪元素,通过 content 来指定内容,before 就是在前面,after 就是在后面(哇好有道理呢)
- 用途一般是加个 icon 啥的,content 可以为 url(...)
- 不能应用在替换元素上,比如 `<img>`
- 伪元素不支持嵌套,也就是说伪元素的父元素不可以为伪元素
使用例:
```css
a {
color: #0000ff;
text-decoration: none;
}
```css
a {
color: #0000ff;
text-decoration: none;
}
a::before {
content: '🔗';
}
```
a::before {
content: '🔗';
}
```
- 使用 inherit 使子元素拥有与父元素相同的特定属性值
使用例:
- 使用 inherit 使子元素拥有与父元素相同的特定属性值
使用例:
```css
div {
position: relative;
background: url('your-image-url.jpg');
}
```css
div {
position: relative;
background: url('your-image-url.jpg');
}
div::before {
content: '';
position: absolute;
top: 0;
left: 0;
background: inherit;
z-index: -1;
}
```
div::before {
content: '';
position: absolute;
top: 0;
left: 0;
background: inherit;
z-index: -1;
}
```
## !important 相关
- 不到万不得已不要用,是不好的写法
- 如果你的 important 不够 important,那可以写 class 的时候多写点前缀,例:
- 不到万不得已不要用,是不好的写法
- 如果你的 important 不够 important,那可以写 class 的时候多写点前缀,例:
```scss
// 一般
.ant-slider-rail {
background-color: rgb(141, 93, 56) !important;
}
// 优先级特别高
.slider .ant-slider .ant-slider-rail {
background-color: rgb(141, 93, 56) !important;
}
```
```scss
// 一般
.ant-slider-rail {
background-color: rgb(141, 93, 56) !important;
}
// 优先级特别高
.slider .ant-slider .ant-slider-rail {
background-color: rgb(141, 93, 56) !important;
}
```
## xx[a=xxx]的使用
- 这玩意叫属性选择器
- 案例:
- 这玩意叫属性选择器
- 案例:
```css
a {
color: blue;
}
/* 以 "#" 开头的页面内部链接 */
a[href^='#'] {
background-color: gold;
}
/* 包含 "example" 的链接 */
a[href*='example'] {
background-color: silver;
}
/* 包含 "insensitive" 的链接,不区分大小写 */
a[href*='insensitive' i] {
color: cyan;
}
/* 包含 "cAsE" 的链接,区分大小写 */
a[href*='cAsE' s] {
color: pink;
}
/* 以 ".org" 结尾的链接 */
a[href$='.org'] {
color: red;
}
/* 以 "https" 开始,".org" 结尾的链接 */
a[href^='https'][href$='.org'] {
color: green;
}
```
- 属性不一定要是 href 什么的,自己定也没关系。
- 案例:
```css
/* 将所有包含 `lang` 属性的 <div> 元素的字重设为 bold */
div[lang] {
font-weight: bold;
}
/* 将所有语言为美式英语的 <div> 元素的文本颜色设为蓝色 */
div[lang~='en-us'] {
color: blue;
}
/* 将所有语言为葡萄牙语的 <div> 元素的文本颜色设为绿色 */
div[lang='pt'] {
color: green;
}
```
## grid
```css
a {
color: blue;
.container {
display: grid;
grid-template-columns: repeat(2, 100px 20px 80px);
/* repeat 配合auto-fill/auto-fit 配合minmax 实现自适应布局 */
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
grid-row-gap: 20px;
grid-column-gap: 20px;
/* 先行后列,尽可能填满 */
grid-auto-flow: row dense;
}
/* 以 "#" 开头的页面内部链接 */
a[href^='#'] {
background-color: gold;
}
/* 包含 "example" 的链接 */
a[href*='example'] {
background-color: silver;
}
/* 包含 "insensitive" 的链接,不区分大小写 */
a[href*='insensitive' i] {
color: cyan;
}
/* 包含 "cAsE" 的链接,区分大小写 */
a[href*='cAsE' s] {
color: pink;
}
/* 以 ".org" 结尾的链接 */
a[href$='.org'] {
color: red;
}
/* 以 "https" 开始,".org" 结尾的链接 */
a[href^='https'][href$='.org'] {
color: green;
.item-1 {
/* 边框所对应的网格线 */
/* grid-column属性是grid-column-start和grid-column-end的合并简写形式,grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。 */
grid-column-start: 2;
grid-column-end: 4;
grid-column: 2/4;
grid-row: 1/2;
}
```
## point-event
- 属性不一定要是 href 什么的,自己定也没关系。
- 案例:
当为none时,所有点击事件无效
```css
/* 将所有包含 `lang` 属性的 <div> 元素的字重设为 bold */
div[lang] {
font-weight: bold;
}
/* 将所有语言为美式英语的 <div> 元素的文本颜色设为蓝色 */
div[lang~='en-us'] {
color: blue;
}
/* 将所有语言为葡萄牙语的 <div> 元素的文本颜色设为绿色 */
div[lang='pt'] {
color: green;
}
```
##
+99 -1
View File
@@ -1,3 +1,101 @@
# 杂谈 记录一些碎碎念
---
npx用来临时使用一个库(如rollup)
npx 用来临时使用一个库(如 rollup)
---
强缓存和协商缓存的 header 参数
强缓存:
Expires:过期时间,如果设置了时间,则浏览器会在设置的时间内直接读取缓存,不再请求
Cache-Control:当值设为 max-age=300 时,则代表在这个请求正确返回时间(浏览器也会记录下来)的 5 分钟内再次加载资源,就会命中强缓存。
cache-control:除了该字段外,还有下面几个比较常用的设置值:
(1) max-age:用来设置资源(representations)可以被缓存多长时间,单位为秒;
(2) s-maxage:和 max-age 是一样的,不过它只针对代理服务器缓存而言;
(3)public:指示响应可被任何缓存区缓存;
(4)private:只能针对个人用户,而不能被代理服务器缓存;
(5)no-cache:强制客户端直接向服务器发送请求,也就是说每次请求都必须向服务器发送。服务器接收到 请求,然后判断资源是否变更,是则返回新内容,否则返回 304,未变更。这个很容易让人产生误解,使人误 以为是响应不被缓存。实际上 Cache-Control: no-cache 是会被缓存的,只不过每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。
(6)no-store:禁止一切缓存(这个才是响应不被缓存的意思)。
---
mvvm:
vm: 关注绑定器,将数据和视图绑定,自动更新,低耦合。model仅关注数据更新
---
垃圾回收相关:
window.gc: 手动调用垃圾回收
现代主要使用标记清除法。
进入执行环境的时候标记上。
离开环境的时候直接回收。
常见的内存泄漏:
全局变量,解决方式: 全局变量
定时器未清除:记得及时清除
闭包: 解决方式: 及时设置为null
dom元素删除后未清除: 解决方式: 及时设置为null
栈(Stack)
特点:栈是一种后进先出(LIFO, Last In First Out)的数据结构。
存储内容:用于存储简单的数据类型(如数字、字符串、布尔值)和函数调用上下文。
内存分配和释放:内存分配和释放非常快速,直接在栈顶操作。函数调用结束后,栈帧自动释放。
作用:主要用于管理函数调用和局部变量。
堆(Heap)
特点:堆是一种无序的数据结构,用于动态分配内存。
存储内容:用于存储复杂的数据类型(如对象、数组)。
内存分配和释放:内存分配比较灵活,但管理和回收内存需要垃圾回收机制(GC, Garbage Collection)来处理。
作用:用于存储需要动态分配的较大数据块和复杂数据结构。
---
babel相关:
Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
---
es6几个主要的:
1. let, const
2. 箭头函数
3. class
4. 模板字符串
5. 解构
6. 函数传参默认值&rest
---
http响应头请求头
请求头:
content-type: 请求的数据的类型
Authorization: 身份验证,如JWT这样的
UA: 浏览器环境
响应头:
set-cookie
content-length
cache-control
跨域cookie需要服务器进行设置
---
SEO优化
1. 大量使用语义化标签
2. 保证关键词覆盖率,title之类,配置meta信息
3. 制定一个站点地图,放在“robot.txt”中
4. 结构化数据
+179 -24
View File
@@ -1,37 +1,192 @@
# 以下是关于 ts(以及任何关于 ts 的不限于语法,技巧之类的学习心得)
## any unknown void never
- any 表示任意类型。这导致不会对类型进行任何检查,用太多不太好就是了。
- unknown 表示位置类型。看作any的安全版本。可以赋值为任何类型,但在使用之前必须进行类型检查或类型断言。
- void 代表没有返回值。
- never 代表永远不会有任何返回值,如死循环或抛出异常。
- any 表示任意类型。这导致不会对类型进行任何检查,用太多不太好就是了。
- unknown 表示位置类型。看作 any 的安全版本。可以赋值为任何类型,但在使用之前必须进行类型检查或类型断言。
- void 代表没有返回值。
- never 代表永远不会有任何返回值,如死循环或抛出异常。
## 接口 interface
- 基本可以认为是声明object类型用的东西
- 基本可以认为是声明 object 类型用的东西
## 泛型 <T>
- 实际上可以理解为是一种类型的变量
- 如:
```ts
function identity<T>(arg: T): T {
return arg
- 实际上可以理解为是一种类型的变量
- 如:
```ts
function identity<T>(arg: T): T {
return arg
}
// 使用泛型函数
let result = identity<string>('Hello')
console.log(result) // 输出: Hello
let numberResult = identity<number>(42)
console.log(numberResult) // 输出: 42
// 基本语法
interface Pair<T, U> {
first: T
second: U
}
// 使用泛型接口
let pair: Pair<string, number> = { first: 'hello', second: 42 }
console.log(pair) // 输出: { first: 'hello', second: 42 }
```
## 箭头函数与普通函数的区别
- 箭头函数没有 yield
- 无 prototype
- 没有 this 和 arguments
## 使用 Object.freeze()
- Object.freeze() 可以冻结一个对象,使其不能添加、删除或修改属性。
```ts
const obj = { key: 'value' };
Object.freeze(obj);
obj.key = 'new value'; // 无效
obj.newKey = 'new value'; // 无效
delete obj.key; // 无效
console.log(obj);
```
## 使用 Object.defineProperty()使对象某一 key 其不可变
- Object.defineProperty() 可以定义对象属性,并使其不可变。
```ts
const obj = {};
Object.defineProperty(obj, 'key', {
value: 'value',
writable: false,
configurable: false // 不可配置的
});
obj.key = 'new value'; // 无效
delete obj.key; // 无效
console.log(obj); // 输出: { key: 'value' }
```
## Object.seal()。
- Object.seal() 可以让对象不能添加或删除属性,但允许修改现有属性的值。
```ts
const obj = { key: 'value' };
Object.seal(obj);
obj.key = 'new value'; // 有效
obj.newKey = 'new value'; // 无效
delete obj.key; // 无效
console.log(obj);
```
## 判断是否为数组
- Array.isArray()
- instanceof Array
- obj.**proto** === [].**proto**
## 是否为 NaN
- Number.isNaN()
## obj 可迭代
- 实现了迭代器协议(拥有 Symbol.iterator 方法)实现了迭代器协议(拥有 Symbol.iterator 方法)
```ts
const iterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
}
```
// 使用泛型函数
let result = identity<string>('Hello')
console.log(result) // 输出: Hello
## promise新的
let numberResult = identity<number>(42)
console.log(numberResult) // 输出: 42
- Promise.race(iterable) 接受一个可迭代对象,返回第一个解决或拒绝的 Promise 的结果。
- Promise.allSettled(iterable) 接受一个可迭代对象,返回一个 Promise,所有 Promise 无论解决或拒绝都会返回结果。
- Promise.any(iterable) 接受一个可迭代对象,返回第一个成功解决的 Promise 的结果。如果所有 Promise 都被拒绝,则返回一个拒绝的 Promise。
// 基本语法
interface Pair<T, U> {
first: T
second: U
}
## deepReadonly
```ts
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}
```
## callable的对象
```ts
const callableObject = {
[Symbol('callable')](...args) {
console.log('Object called with args:', ...args);
// 执行一些操作并返回结果
return args.reduce((sum, val) => sum + val, 0);
}
}
```
## 异步迭代
```ts
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield await new Promise(resolve => setTimeout(() => resolve(1), 1000));
yield await new Promise(resolve => setTimeout(() => resolve(2), 1000));
yield await new Promise(resolve => setTimeout(() => resolve(3), 1000));
}
};
(async function() {
for await (const value of asyncIterable) {
console.log(value); // 输出: 1, 2, 3,每个值之间间隔1秒
}
})
```
---
二进制/文件处理
blob: 一种类文件对象,只能使用fileReader进行异步读取,读取为arrayBuffer
arraybuffer: 一种通用的二进制数据缓冲区,需要通过视图(如uint8array)进行修改
---
关于闭包,有逻辑的回答:
闭包(closure)指有权访问另一个函数作用域中变量的函数。 ----- JavaScript 高级程序设计
闭包有什么用?
延伸变量作用域范围,读取函数内部的变量
让这些变量的值始终保持在内存中
简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。
---
weakMap
key必须为一个obj
可以用于给一个obj附加一些生命周期相同的数据内容(如缓存)
// 使用泛型接口
let pair: Pair<string, number> = { first: 'hello', second: 42 }
console.log(pair) // 输出: { first: 'hello', second: 42 }
```
+56 -3
View File
@@ -4,7 +4,8 @@
---
# 子子组件之间的通信可以通过事件总线(eventBus)实现
---
# doucument.createElement出来的东西不及时销毁就会一直游离在外面不被释放,积累下来很不好。
# doucument.createElement出来的东西不及时销毁就会一直游离在外面不被释放,积累下来很不好。(似乎是错误的)
---
@@ -12,7 +13,7 @@
组件设计可以分成业务组件,展示组件,展示组件只负责以对应的形式展示对应的数据,对于业务的处理(如增删查改),则需要通过emit或其他方法交给业务组件处理
---
# 路由返回拦截hook
# 路由返回拦截hook(路由守卫)
* 当点击返回键(浏览器或者是页面上的路由返回功能)时触发,形式如下:
```ts
import { onBeforeRouteLeave } from 'vue-router'
@@ -27,7 +28,7 @@ onBeforeRouteLeave((to, from, next) => {
next(true)
})
```
* 当next(false时,取消路由原有的返回功能)
* 当next===false时,取消路由原有的返回功能
---
## 具名作用域插槽
* 具名作用域插槽的工作方式也是类似的,插槽 props 可以作为 v-slot 指令的值被访问到
@@ -82,4 +83,56 @@ example:
</div>
</template>
</el-popover>
```
# 路由相关:
* 路由守卫
- - beforeEach 全局前置守卫
作用:
主要用于在路由跳转前进行权限验证、页面加载状态的设置等操作。例如,判断用户是否已经登录,如果没有登录且要访问需要登录才能访问的页面,就可以将用户重定向到登录页面。
它可以对每一次路由跳转进行全局拦截,是控制路由访问权限的重要手段。
- - afterEach全局后置守卫
作用:
它在路由跳转完成后被调用,主要用于记录页面访问历史、修改页面标题或者进行一些不需要阻塞路由跳转的操作。
例如,根据不同的路由来更新文档的标题,或者发送页面访问统计数据到服务器。
- - 全局解析守卫(beforeResolve)的触发时机
全局解析守卫beforeResolve在路由导航被触发后,在所有组件内守卫和异步路由组件被解析之前调用。它是在beforeEach之后,但是在组件实例创建和beforeRouteEnter等组件内守卫之前执行。这意味着它处于路由导航过程的一个中间阶段,此时路由已经被匹配,但组件还没有完全解析和进入。
主要作用
数据预获取:
可以用于获取组件渲染所需的数据。与beforeEach不同的是,beforeResolve更专注于确保在组件真正开始渲染之前,所有必要的数据都已经获取并准备好。例如,对于一个包含多个嵌套组件的复杂页面,其中每个组件都需要从服务器获取数据,beforeResolve可以协调这些数据获取操作,确保所有数据都准备好后再进行组件渲染。
处理异步操作的集中点:
它为处理整个路由导航过程中的异步操作提供了一个集中的位置。在大型应用中,可能会有多个异步操作需要在路由跳转时完成,如加载第三方脚本、初始化插件等。beforeResolve可以用于确保这些异步操作都顺利完成后再继续路由解析过程。
- - 组件路由守卫
```vue
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'
// 与 beforeRouteLeave 相同,无法访问 `this`
onBeforeRouteLeave((to, from) => {
const answer = window.confirm(
'Do you really want to leave? you have unsaved changes!'
)
// 取消导航并停留在同一页面上
if (!answer) return false
})
const userData = ref()
// 与 beforeRouteUpdate 相同,无法访问 `this`
onBeforeRouteUpdate(async (to, from) => {
//仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id)
}
})
</script>
```
+86
View File
@@ -0,0 +1,86 @@
```ts
import {
defineComponent,
watch,
onMounted,
onBeforeUnmount,
h,
getCurrentInstance,
type PropType,
} from 'vue-demi'
import ResizeObserver from './ResizeObserver'
import type { IOptions } from './types'
// const component = {
// name: 'Home',
// props:{
// data: String,
// },
// setup(props, context){
// // props.data
// // context.attrs context.slots context.emit
// }
// }
export default defineComponent({
name: 'ResizeObserverComponent',
props: {
target: [String, Object] as PropType<string | HTMLElement>,
disabled: Boolean as PropType<boolean>,
immediate: Boolean as PropType<boolean>,
delay: {
type: Number as PropType<number>,
default: 150
}
},
setup(props, { slots }) {
let ro: ResizeObserver | null = null
watch(() => props.disabled, (val) => {
if (val) {
ro?.disconnect()
} else {
ro?.observe()
}
})
onMounted(() => {
// const { target, disabled, limiter, wait } = toRefs(props)
// 拿到当前组件的实例(注意已挂载)
const vm = getCurrentInstance()?.proxy
// 先用$el
let $el: HTMLElement = vm?.$el as HTMLElement
if (props.target) {
if (typeof props.target === 'string') {
$el = document.querySelector(props.target) as HTMLElement
} else if (props.target instanceof HTMLElement) {
$el = props.target
}
}
const options: IOptions = {
delay: props.delay,
immediate: props.immediate,
resize: (data, elem) => {
vm?.$emit('resize', data, elem)
}
}
ro = new ResizeObserver($el, options)
})
// 销毁 ResizeObserver实例
onBeforeUnmount(() => {
if (ro) {
ro.destroy()
}
})
// 如果有单个子元素则直接渲染子元素
const defaultContent = slots.default?.()
return () => (
(defaultContent && defaultContent.length === 1)
? defaultContent[0]
: h('div', defaultContent)
)
}
})
```
View File
Whitespace-only changes.