Hezhiyi.com
分类

【React】学习笔记-基础篇

虚拟 DOM 的原理是什么?为什么比直接操作 DOM 高效?

  • 虚拟 DOM 是一个轻量的 JS 对象,用来描述真实 DOM 的层次和属性。
  • 通过 Diff 算法最小化 DOM 操作,减少重绘和回流。

JSX 是什么?和普通 JavaScript 的区别?

  • JSX 是语法糖,最终会被 Babel 编译为 React.createElement() 调用。

数据流

  • 单向数据流,自上而下传递。
  • 父组件通过 props 把数据传递给子组件;
  • 子组件可以通过回调函数通知父组件。

Props

  • PropTypes 定义类型
  • defaultProps 定义默认值
  • this.props.children 表示组件的所有子节点
  • 不要把 props 复制到 state 中,要尽可能把 props 当作数据源(避免反模式)

高阶组件(HOC)

  • 用于复用组件逻辑。本质上是一个函数,通过接收一个组件并返回一个新组件

PureComponent 和 React.memo

  • PureComponent 会对 props 和 state 进行浅比较
  • memo 只对 props 进行浅比较

<Fragment><> (空标签)的区别

  • 只有 <Fragment> 可以带 key 属性,这在列表渲染时非常重要

类组件和函数组件的区别?

  • 语法与结构
class MyComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}

function MyComponent(props) {
  return <div>Hello, {props.name}</div>;
}
  • 状态管理
  • 类组件通过 this.state 定义状态,this.setState() 更新状态
  • 函数组件使用 Hooks 的 useState 管理状态
  • 生命周期与副作用
  • 类组件通过生命周期处理副作用
  • 函数组件通过 useEffect 替代生命周期
  • this 的绑定问题
  • 类组件通过手动绑定事件函数的 this
class
 Button extends React.Component {
  handleClick() { console.log(this); } // this 可能为 undefined
  render() {
    return <button onClick={this.handleClick.bind(this)}>Click</button>;
  }
}
  • 函数组件没有 this,直接访问 props 和状态
function Button() {
  const handleClick = () => console.log("No this!");
  return <button onClick={handleClick}>Click</button>;
}
  • 性能优化
  • 类组件使用 shouldComponentUpdatePureComponent 避免不必要的渲染
  • 函数组件使用 React.memo 进行浅比较

【状态管理】

React 中的状态提升(Lifting State Up)是什么?

  • 把状态提升到父组件进行管理,子组件通过 props 读取数据。

Context API 的作用?如何避免不必要的渲染?

  • Context(上下文) 是 React 提供的跨层级组件数据传递方案,用于解决多层组件嵌套时(逐层传递 props)的问题。
  • 核心作用
  • 跨组件共享数据(如主题、用户信息、全局配置等)
  • 避免中间组件透传 props(减少冗余代码)

MobX / Redux

  • 全局状态管理,把状态抽离到组件之外。

Redux

  • 工作流程:
    1. 定义 Store:集中管理全局状态(createStore)。
    2. 派发 Action:组件通过 dispatch(action) 发出状态修改请求(action 是一个描述“发生了什么”的普通对象)。
    3. 执行 Reducer:根据 action.type,纯函数 reducer 计算新状态(不可变更新)。
    4. 更新视图:Store 通知订阅者(如 React 组件),触发重新渲染。
  • 核心概念:
    • 单向数据流:View → Action → Reducer → Store → View
    • 三大原则:单一数据源、状态只读、纯函数修改。
  • 总结:
    • 组件 dispatch → Reducer 处理 → Store 更新 → 视图同步

MobX

  • 工作流程:
    1. 定义 Observable State:用 @observable 或 makeObservable 标记可变状态。
    2. 修改 State:在 @action 函数中更新状态(直接赋值/修改对象属性)。
    3. 自动追踪依赖:组件用 observer 包裹,自动订阅其依赖的状态。
    4. 触发更新:状态变化时,依赖它的组件自动重渲染。
  • 核心概念:
    • 响应式编程:像 Excel 公式一样自动更新(无需手动 dispatch/reducer)。
    • 直接修改状态(但通过 action 规范变更)。
  • 总结:
    • 响应式状态,自动追踪依赖,修改即更新

【性能优化】

React 的渲染机制是怎样的?如何避免不必要的渲染?

  • 使用 React.memo、useMemo、useCallback、避免内联对象/函数。

React 的 key 属性有什么作用?

  • 帮助 React 识别元素变化,优化列表渲染。

实现代码分割(Code Splitting)

  • 动态 import() 语法
  • 动态 import() 是 ES2020 引入的语法,返回一个 Promise:
// 普通模块中使用
import("./math").then(math => {
  console.log(math.add(16, 26));
});

// React 组件中使用
import("./OtherComponent").then(OtherComponent => {
  // 使用加载的组件
});
  • React.lazy + Suspense
  • React.lazy 和 Suspense 来实现组件的懒加载:
import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

WEB前端-JS篇

小数精度处理

  • 使用 toFixed 取后几位小数
  • 把小数转为整数再进行运算
  • 使用精度运算库,如:big.js

for…infor…of 的区别

  • for-in 历遍对象,通常获取 key(类似 Object.keys)
  • for-of 历遍可迭代对象,如 ArrayMapSet

任务队列(Task Queue)

  • 先执行同步再执行异步
  • 核心作用:处理异步代码的调度和执行
  • 宏任务:setTimeoutsetIntervalI/O
  • 微任务:Promise 回调(.then / .catch/ .finally)、MutationObserver 回调等
  • 微任务优先级高于宏任务
  • 调用 fetch 会同步执行并立即返回一个 promise

call | apply | bind

均用于改变函数内部 this 的指向

const obj = { name: "Alice" };

function greet() {
  console.log(`Hello, ${this.name}!`);
}

greet.call(obj);      // Hello, Alice!
greet.apply(obj);     // Hello, Alice!
const boundGreet = greet.bind(obj);
boundGreet();         // Hello, Alice!

ES 新特性:

变量声明

letconst

箭头函数

简化函数语法,自动绑定 this

模板字符串

`Hello ${name}`

解构赋值

const { age, name } = user;
const [first, second] = [1, 2];

默认参数

扩展运算符

const arr1 = [1, 2];
const arr2 = [...arr1, 3]; // [1, 2, 3]; // 合并数组
const objCopy = { ...originalObj }; // 合并对象

Promise 和 异步处理

Promise.all – 等待所有 Promise 对象都执行完成 Promise.race – 返回第一个完成的 Promise(无论成功失败) Promise.any – 返回第一个成功的 Promise

模块化:importexport

Set, Map

let s = new Set(); s.add(‘a’).add(‘b’)
let m = new Map(); m.set(’age’, 16)

数组的 includes,检查是否包含某元素

async / await

底层实现机制: async/await 的核心是通过 Generator 函数和自动执行器实现的:

  1. async 函数本质上是一个返回 Promise 的 Generator 函数;
  2. await 相当于 yield,暂停函数执行;
  3. 有一个自动执行器负责处理 Promise 的 resolve/reject 并继续执行。

Generator 函数的语法糖,省去手动 next() 的步骤

Object.values() 和 Object.entries()

Object.values({ a: 1, b: 2 }); // [1, 2]
Object.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]

字符串填充:padStart() 和 padEnd()

"5".padStart(2, "0"); // "05"

空值合并运算符

const value = input ?? "default";

动态导入模块

const module = await import('./module.js')

replaceAll 替换所有匹配的子串

"a.b.c".replaceAll(".", "-"); // "a-b-c"

require 和 import

  • 分别属于 CommonJS 和 ES 两种不同模块系统
  • require 动态加载,运行时解析
  • import 静态加载,编译时解析
  • Proxy
    • 数据绑定与响应式系统:通过 set 拦截属性赋值,触发副作用(如重新渲染)
    • 属性访问控制和校验:限制对象属性的访问或赋值

微信小程序:

OpenID & UnionID

OpenID

  • 用户在当前小程序中的唯一标识
  • 用途:用于识别用户在当前小程序内的身份(如用户数据存储、业务逻辑处理)
  • 获取:通过 wx.login() 获取 code,后端用 code 调用微信接口换取 OpenID

UnionID

  • 用户在微信的唯一标识
  • 用途:实现跨小程序、公众号用户身份统一
  • 获取:通过 wx.getUserInfo() 获取 encryptedData, iv,发送到后端解密,或者通过按钮触发授权

性能优化:

  1. 文本压缩(css, js, html)
  2. 图片压缩
  3. 合并资源(合并文本、雪碧图)
  4. 图片懒加载
  5. 合并请求
  6. 缓存资源(设置浏览器头、设置 html head)
  7. 使用 CDN
  8. gzip 压缩
  9. 减少 DOM 操作
  10. CSS 样式置顶、JS 脚本置底
  11. 防抖和节流
    • 防抖:保证N秒内执行一次,如果N秒内触发将再执行并重新计算时间
    • 节流:保证N秒内只能触发一次

WEB前端-CSS篇

CSS3 新增属性

1. 选择器(Selectors)

CSS3 新增了许多强大的选择器,可以更精确地匹配元素。

选择器示例描述
属性选择器input[type="text"]匹配具有特定属性的元素
结构伪类:nth-child(n)匹配第 n 个子元素
:first-of-type匹配同类型的第一个元素
:last-child匹配最后一个子元素
:not(selector)排除匹配的元素
UI 伪类:checked匹配被选中的表单元素(如复选框)
:disabled匹配禁用的表单元素
:enabled匹配可用的表单元素
目标伪类:target匹配当前 URL 的锚点目标元素

2. 盒模型(Box Model)

CSS3 提供了更灵活的盒模型控制方式。

属性描述
box-sizing: border-box使 widthheight 包含 paddingborder
resize允许用户调整元素大小(bothhorizontalvertical
outline-offset设置轮廓(outline)与边框的偏移距离

3. 背景与边框(Background & Border)

CSS3 增强了背景和边框的样式控制。

背景(Background)

属性描述
background-size控制背景图片大小(covercontain100% 100%
background-clip定义背景绘制区域(border-boxpadding-boxcontent-box
background-origin定义背景定位的基准区域
background-attachment: local背景随内容滚动
background: url(img1.png), url(img2.png);多背景

边框(Border)

属性描述
border-radius圆角边框(border-radius: 10px;
box-shadow盒子阴影(box-shadow: 5px 5px 10px #888;
border-image使用图片作为边框(border-image: url(border.png) 30 round;

4. 渐变(Gradients)

CSS3 支持线性渐变和径向渐变。

类型示例描述
线性渐变background: linear-gradient(to right, red, blue);从左到右渐变
径向渐变background: radial-gradient(circle, red, yellow);从中心向外渐变
重复渐变background: repeating-linear-gradient(45deg, red, red 10px, blue 10px, blue 20px);重复渐变

5. 过渡(Transitions)

CSS3 过渡允许属性在一定时间内平滑变化。

属性描述
transition-property指定过渡的属性(如 widthopacity
transition-duration过渡持续时间(如 1s
transition-timing-function过渡速度曲线(easelinearcubic-bezier()
transition-delay过渡延迟时间
简写transition: width 1s ease 0.5s;

6. 动画(Animations)

CSS3 动画比过渡更强大,支持关键帧控制。

属性描述
@keyframes定义动画关键帧
animation-name指定动画名称
animation-duration动画持续时间
animation-timing-function动画速度曲线
animation-delay动画延迟时间
animation-iteration-count动画播放次数(infinite 表示无限循环)
animation-direction动画方向(normalreversealternate
animation-fill-mode动画结束后保持状态(forwardsbackwards
简写animation: move 2s ease infinite;

示例:

@keyframes move {
  0% { transform: translateX(0); }
  100% { transform: translateX(100px); }
}
div {
  animation: move 2s ease infinite;
}

7. 变形(Transforms)

CSS3 变形允许对元素进行 2D/3D 变换。

2D 变形:

属性描述
transform: translate(x, y)移动元素
transform: rotate(45deg)旋转元素
transform: scale(1.5)缩放元素
transform: skew(30deg)倾斜元素
组合变换transform: rotate(45deg) scale(1.2);

3D 变形:

属性描述
transform: translate3d(x, y, z)3D 移动
transform: rotateX(45deg)绕 X 轴旋转
transform: perspective(500px)设置 3D 透视距离

8. 弹性布局(Flexbox)

CSS3 Flexbox 提供更灵活的布局方式。

属性描述
display: flex启用 Flex 布局
flex-direction主轴方向(rowcolumn
justify-content主轴对齐方式(centerspace-between
align-items交叉轴对齐方式(centerstretch
flex-wrap是否换行(wrapnowrap
flex-grow定义项目的放大比例
flex-shrink定义项目的缩小比例
flex-basis定义项目的初始大小

9. 网格布局(Grid)

CSS3 Grid 提供二维布局系统。

属性描述
display: grid启用 Grid 布局
grid-template-columns定义列宽(如 1fr 2fr
grid-template-rows定义行高
grid-gap定义行列间距
grid-column / grid-row定义项目占据的网格区域
<!DOCTYPE html>
<html>
<head>
    <style>
        .grid-container {
            display: grid;
            grid-template-columns: 100px 200px auto; /* 三列:固定100px,固定200px,剩余空间 */
            gap: 10px;
            background-color: #2196F3;
            padding: 10px;
        }

        .grid-item {
            background-color: rgba(255, 255, 255, 0.8);
            border: 1px solid rgba(0, 0, 0, 0.8);
            padding: 20px;
            font-size: 30px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="grid-container">
        <div class="grid-item">1</div>
        <div class="grid-item">2</div>
        <div class="grid-item">3</div>  
        <div class="grid-item">4</div>
        <div class="grid-item">5</div>
        <div class="grid-item">6</div>  
        <div class="grid-item">7</div>
        <div class="grid-item">8</div>
        <div class="grid-item">9</div>  
    </div>
</body>
</html>

10. 媒体查询(Media Queries)

CSS3 媒体查询允许针对不同设备应用不同样式。

/* 屏幕宽度小于 600px 时生效 */
@media (max-width: 600px) {
  body { background: lightblue; }
}

BEM 命名规范

BEM(Block-Element-Modifier)是一种流行的 CSS 命名方法论,旨在提高代码可读性、可维护性和可复用性。其核心思想是通过模块化的方式组织 CSS 类名,避免样式冲突。

1. BEM 基本结构

BEM 将界面拆分为三个部分:部分描述示例
Block独立的、可复用的组件(如按钮、卡片、导航栏)。.btn.card
Element属于 Block 的子元素,不能单独使用(如按钮的图标、卡片的标题)。.btn__icon.card__title
Modifier表示 Block 或 Element 的状态或变体(如禁用按钮、大号卡片)。.btn--disabled.card--large

2. 命名规则

(1) Block(块)
  • 使用单一单词短横线连接-)的命名方式。
  • 代表一个独立的组件,不依赖其他元素。
.header { ... }       /* 页眉 */
.menu { ... }         /* 菜单 */
.search-box { ... }   /* 搜索框 */
(2) Element(元素)
  • 格式:Block名称__Element名称双下划线 __ 连接)。
  • 表示属于 Block 的一部分,不能脱离 Block 使用。
.menu__item { ... }          /* 菜单项 */
.search-box__input { ... }   /* 搜索框的输入框 */
.card__title { ... }         /* 卡片的标题 */
(3) Modifier(修饰符)
  • 格式:Block--ModifierBlock__Element--Modifier双短横线 -- 连接)。
  • 表示 Block 或 Element 的不同状态或样式变体。
.button--primary { ... }     /* 主要按钮 */
.button--disabled { ... }    /* 禁用按钮 */
.menu__item--active { ... }  /* 当前选中的菜单项 */

3. 实际代码示例

HTML 结构

<!-- Block: card -->
<div class="card card--highlight">
  <!-- Element: card 的子元素 -->
  <h2 class="card__title">标题</h2>
  <p class="card__content">内容...</p>
  <!-- 带 Modifier 的 Element -->
  <button class="card__button card__button--large">点击</button>
</div>

CSS 样式

/* Block */
.card { 
  border: 1px solid #ccc;
  padding: 16px;
}

/* Modifier: 高亮卡片 */
.card--highlight {
  background: #f5f5f5;
}

/* Element: 卡片标题 */
.card__title {
  font-size: 18px;
  color: #333;
}

/* Element: 卡片按钮 */
.card__button {
  padding: 8px 16px;
}

/* Modifier: 大号按钮 */
.card__button--large {
  padding: 12px 24px;
}

WEB前端-HTML篇

新增标签元素

  • 语义化结构标签:
    <header>, <footer>, <nav>, <main>, <article>, <section>, <aside>, <figure>, <figcaption>, <time>, <mark>
  • 多媒体标签:
    <audio>, <video>, <source>, <track>, <canvas>, <svg>
  • 表单增强元素:
    <datalist>, <output>, <meter>, <progress>

    新增 Input 类型: date, datetime, email, number, range, tel, color, time, url, search

  • 其它标签:
    <details>, <summary>, <dialog>, <template>

本地存储

生命周期:

  • cookie 可设置过期时间
  • localStorage 永久存储
  • sessionStorage 关闭标签页自动清除

存储大小:

  • cookie 4KB
  • sessionStorage 5MB – 10MB
  • localStorage 5MB – 10MB

作用域:

  • cookie:可设置 Domain 和 Path,控制哪些域名和路径可以访问
  • localStorage:同源策略下的所有窗口和标签页共享
  • sessionStorage:仅当前标签页有效,即使同源的其他标签页也无法访问

以下是整理成 Markdown 表格的浏览器存储特性对比:

特性CookielocalStoragesessionStorage
生命周期可设置过期时间(Expires/Max-Age永久存储,除非手动清除关闭标签页后自动清除
存储大小约 4KB5MB – 10MB(不同浏览器可能有差异)5MB – 10MB(同 localStorage)
作用域通过 DomainPath 控制访问范围同源策略下的所有窗口/标签页共享仅当前标签页有效,同源其他标签页不可访问
数据发送每次请求自动携带在 HTTP 头部不自动发送,仅客户端存储不自动发送,仅客户端存储
API 易用性需手动解析字符串直接使用 setItem/getItem 等操作同 localStorage

补充说明

  • 同源策略:协议、域名、端口必须完全相同。
  • 安全建议:
    • Cookie 敏感数据建议设置 HttpOnlySecure
    • 大容量数据优先使用 localStoragesessionStorage
    • sessionStorage 适合临时数据(如表单填写中途防止丢失)。

<script> 加载方式

  • 默认同步阻塞 HTML 解析
  • defer 延迟执行直至DOM解析完后
  • async 异步引入,下载完成后立即执行

2025佛山50公里徒步

今年是我来佛山定居的第十年,所以去参加了50km徒步纪念一下。

6:30 AM 起床

一大早就起床,吃完早餐就骑电驴向集结地文华公园出发。

8:24 AM 起点·文华公园,人山人海

到现场直接吓懵 —— 人也太多了吧!电视塔下面全是人。之前我还想走50公里不是普通的运动量,参加的人应该不多,结果发现满头白发的老人、三岁小孩都来参加,看来我低估了大家对这个活动的积极性。好,从此刻正式开始!

09:53 AM 第一签:升平里(5KM)

开局像过年游花市,大家都是一个挨一个,沿途的路都围蔽了。就这样慢吞吞地走了1.5小时。心想,这样走岂不是晚上十点都走不完?!来到升平里人更多了(是我见过这个地方人最多的一次),赶紧找签到点盖章离开。

11:48 AM 第二签:欧洲工业园C区(12.8KM)

这段感觉人少了不少,原因其实很多人只是为了打个卡发发朋友圈,(毕竟 5km 对现在的人还是极限)。太阳也出来营业了,还好沿途绿道大树也比较多。这一段是考验耐心的,因为要经过一片老旧的工业区,所以风景一般,路边的大货车经过会扬起一片灰尘……

13:24 AM 第三签:城发悦城峯境(17.8KM)

沿汾江河边都是新打造的绿道,风景很不错。沿途都是卖小吃、饮料的小贩。也经过了我一直想去的王借岗公园,又帮我在百度地图点亮了一个片区。

14:29 PM 第四签:绿岛湖国际中心(20.5KM)

距离不远,但人走了一个上午已经有点累,所以走到绿岛湖就在湖边休整了20分钟。在这里汇合身穿浅蓝色衣服的”三水线”驴友,这些都是大神人,因为他们的线路比我们多出14km,也就是说别人一大早7点就已经出发,并且走得很快。其实禅城线算是“作弊”线路,因为它全场是36km,是全部线路中最短的。

15:25 PM 第五签:智慧公园(24.5KM)

这段就开始拼耐力了,阳光猛烈,大树比较少,脚步也渐渐慢下来。不过令我意外的是智慧公园原来很漂亮,又找多了一个休闲的地方。

16:46 PM 第六签:青年公园(30.5KM)

如果认真计算距离和时间,就发现我速度快了很多。不,我没作弊(已经看到很多人骑共享单车跑了),其实原因是身边的队友也受不了骑车去。我只是自己发挥真正的实力 ^_^。PS沿线的公交线路都挤满了人,其实这不是比赛,尽力而为就好。

18:12 PM 终点·世纪莲体育中心(36KM)

突然想起十年前那次30公里徒步,走完整个人都废了,所以这次出发前一直怀疑自己到底行不行。现在看来,身体确实比以前能扛了,但更关键的是——只要咬咬牙,好像也没什么走不完的路。

【Bus World】第一巴士-1路

制造商
广汽比亚迪
车型
GZ6100
比例
1/110
材质
金属
城市
广州
线路
1
运营区间
芳村花园 ↔ 东山
票价
¥2.00

这两天刷淘宝看到TINY微影的最新出品,立即淘了两台,性价比非常不错。可惜自身行程原因,赠送的一汽巴士博物馆入场券无法使用。

介绍

广州公交1路运营于中国广东省广州市越秀区、荔湾区,是市区线路,其历史可追溯至民国十七年(1928年),现在由广州市一汽巴士有限公司一分公司运营。

历史

  • 民国九年(1920年)起,广州开始有搭客客车在市区运营,自民国十二年(1923年)形成4条线路,包括沙河至大东门、东山至西濠口(今沿江西路人民南路口)、东山至沙基东桥、司后街(今越华路)至天字码头4条线路。

  • 民国十七年(1928年),广州当局开始用颜色标注不同路线的4路公交车,其中从黄沙出发,经长堤、永汉路(今北京路)、惠爱路(今中山路)至东山公园的一条公交线路,被标注为黄线,此为现东山总站及广州公交1路最早记载。

  • 民国十八年(1929年),随着广州市区马路相继修筑及公交线路的增多,原有用颜色标注公交线的方式已不再适用,故当局改用数字标注公交线,原黄线公交被标注为1路。

  • 1952年9月8日,伴随着广州市公共汽车公司的成立,广州公交1路诞生,采用由货车改装的“火柴盒”运营,成为广州第一条公交线路。

  • 20世纪六七十年代,广州公交1路开始使用拖卡车和“通道车”运营。

  • 广州修建地铁1号线期间,广州公交1路曾将路线修改为东山至如意坊,地铁1号线竣工后回迁黄沙。

  • 1992年,广州市推行的“前门上车,后门下车”的改革中,广州公交1路线作为首批的试点线路之一,为1993年广州市实行公交“无人售票”奠定了基础。

  • 2000年后,广州公交1路开始使用首批新能源空调车运营。

  • 2003年,广州公交线网大调整,广州公交1路由东山至黄沙改为东山至芳村花园。

  • 2005年,为配合广州地铁6号线施工,广州公交1路始发站由东山(署前路)总站迁往东华南路。

  • 2012年6月14日,东山公交总站复建工程基本完成,广州公交1路重新返回东山(署前路)总站始发。

  • 2022年4月16日,为配合北京路南段(大南路至泰康路)试行全日步行化管理,广州公交1路往东山(署前路)总站方向临时取消停靠北京南站,临时增加停靠万福西站,往芳村花园南门方向临时取消停靠北京路口站,临时增加停靠万福西站。

【JS】判断登录设备是移动端还是PC端

基于 navigator.userAgent 的 User Agent 检测

function isMobileDevice () {
  const ua = navigator.userAgent || navigator.vendor || window.opera;
  const mobileRegex = /android|iphone|ipad|ipod|blackberry|iemobile|opera mini|mobile|windows phone|phone|webos|kindle|tablet/i;
  return mobileRegex.test(ua.toLowerCase());
}

通过 navigator.userAgent 获取浏览器标识字符串‌。正则表达式匹配移动端关键词(如 android、iphone、mobile 等)‌。返回 true 表示移动端,false 表示 PC 端。

‌基于 navigator.userAgent 的插件方案‌

插件:mobile-detect.js

插件通过解析 navigator.userAgent 中的设备标识符(如 Android、iPhone、Windows 等)实现设备判断‌。 支持更细分的设备类型检测(如平板、手机、PC)‌。

import MobileDetect from 'mobile-detect';

const md = new MobileDetect(navigator.userAgent);

if (md.mobile()) {
  console.log("移动端登录设备(手机/平板)");
} else if (md.tablet()) {
  console.log("平板设备");
} else {
  console.log("PC 端设备");
}

广州11号线开通首日体验

早上我和家人去了广州动物园,下午回来赶上了11号线的开通首日,顺便体验一下新线路。

列车进站的时候,大家都掏出手机拍照,我也赶紧拍了几张发朋友圈。11号线的站台和车厢都很大,不愧为A8列车,坐着特别舒服,相比广州其它线路,绝对的王者。而且它是城区环线,所以去哪里换乘都方便。

到了中医学院站,发现人还挺多的,大家都想第一时间体验新线路,而且这个站也是「大站」,以后可以换乘12号线。站台设计很有特色,融入了很多中医药文化的元素。

MIDI音符代码表

MIDI 音符代码是用于表示音符的数字系统,范围从0到127,对应不同的音高和八度。具体如下:

  1. 音符编号:每个音符对应一个唯一的编号,例如:

    • C4(中央C)的编号为60。
    • C5的编号为72。
  2. 音高与编号

    • 编号0对应C-1(最低音)。
    • 编号127对应G9(最高音)。
  3. 八度划分

    • 每增加12,编号提高一个八度。例如,C4为60,C5为72。
  4. 半音关系

    • 相邻编号相差一个半音。例如,C4为60,C#4/Db4为61。
  5. 常用音符示例

    • C4: 60
    • D4: 62
    • E4: 64
    • F4: 65
    • G4: 67
    • A4: 69
    • B4: 71
    • C5: 72
  6. 应用

    • MIDI音符代码用于音乐软件、硬件和数字乐器中,控制音符的播放。

附表:

编号音符代码(二进制码)音符代码(十六进制码)所在音阶音调
0000000000-1C
1000000101-1C#
2000001002-1D
3000001103-1D#
4000010004-1E
5000010105-1F
6000011006-1F#
7000011107-1G
8000100008-1G#
9000100109-1A
1000010100A-1A#
1100010110B-1B
1200011000C0C
1300011010D0C#
1400011100E0D
1500011110F0D#
160010000100E
170010001110F
180010010120F#
190010011130G
200010100140G#
210010101150A
220010110160A#
230010111170B
240011000181C
250011001191C#
2600110101A1D
2700110111B1D#
2800111001C1E
2900111011D1F
3000111101E1F#
3100111111F1G
320100000201G#
330100001211A
340100010221A#
350100011231B
360100100242C
370100101252C#
380100110262D
390100111272D#
400101000282E
410101001292F
4201010102A2F#
4301010112B2G
4401011002C2G#
4501011012D2A
4601011102E2A#
4701011112F2B
480110000303C
490110001313C#
500110010323D
510110011333D#
520110100343E
530110101353F
540110110363F#
550110111373G
560111000383G#
570111001393A
5801110103A3A#
5901110113B3B
6001111003C4C
6101111013D4C#
6201111103E4D
6301111113F4D#
641000000404E
651000001414F
661000010424F#
671000011434G
681000100444G#
691000101454A
701000110464A#
711000111474B
721001000485C
731001001495C#
7410010104A5D
7510010114B5D#
7610011004C5E
7710011014D5F
7810011104E5F#
7910011114F5G
801010000505G#
811010001515A
821010010525A#
831010011535B
841010100546C
851010101556C#
861010110566D
871010111576D#
881011000586E
891011001596F
9010110105A6F#
9110110115B6G
9210111005C6G#
9310111015D6A
9410111105E6A#
9510111115F6B
961100000607C
971100001617C#
981100010627D
991100011637D#
1001100100647E
1011100101657F
1021100110667F#
1031100111677G
1041101000687G#
1051101001697A
10611010106A7A#
10711010116B7B
10811011006C8C
10911011016D8C#
11011011106E8D
11111011116F8D#
1121110000708E
1131110001718F
1141110010728F#
1151110011738G
1161110100748G#
1171110101758A
1181110110768A#
1191110111778B
1201111000789C
1211111001799C#
12211110107A9D
12311110117B9D#
12411111007C9E
12511111017D9F
12611111107E9F#
12711111117F9G

【Bus World】第一巴士-284

制造商
广汽比亚迪
车型
K9FE
比例
1/76
材质
树脂胶
城市
广州
线路
284
运营区间
广园新村 ↔ 员村(绢麻厂)
票价
¥2.00

284这条线路一直陪伴我生活、读书、工作至今,算是我收藏里的无价宝。

介绍

广州公交284路(Guangzhou Public Transport Line284)运营于中国广东省广州市白云区、越秀区、天河区,为市区线路,隶属广州巴士集团有限公司第一分公司。

历史

  • 广州公交284路初期走向为“广园新村—东山”,途经大东门、北京路、纪念堂,由广州市电车公司营运。
  • 1993年,广州公交284路走向由“广园新村—东山”调整为“广园新村—员村生活区”。
  • 约2000年,广州公交284路走向由“广园新村—员村生活区”调整为“广园新村—员村(绢麻厂)”。
载入中