CMS

博客

  • 【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 表格的浏览器存储特性对比:

    特性 Cookie localStorage sessionStorage
    生命周期 可设置过期时间(Expires/Max-Age 永久存储,除非手动清除 关闭标签页后自动清除
    存储大小 约 4KB 5MB – 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音符代码用于音乐软件、硬件和数字乐器中,控制音符的播放。

    附表:

    编号 音符代码(二进制码) 音符代码(十六进制码) 所在音阶 音调
    0 0000000 00 -1 C
    1 0000001 01 -1 C#
    2 0000010 02 -1 D
    3 0000011 03 -1 D#
    4 0000100 04 -1 E
    5 0000101 05 -1 F
    6 0000110 06 -1 F#
    7 0000111 07 -1 G
    8 0001000 08 -1 G#
    9 0001001 09 -1 A
    10 0001010 0A -1 A#
    11 0001011 0B -1 B
    12 0001100 0C 0 C
    13 0001101 0D 0 C#
    14 0001110 0E 0 D
    15 0001111 0F 0 D#
    16 0010000 10 0 E
    17 0010001 11 0 F
    18 0010010 12 0 F#
    19 0010011 13 0 G
    20 0010100 14 0 G#
    21 0010101 15 0 A
    22 0010110 16 0 A#
    23 0010111 17 0 B
    24 0011000 18 1 C
    25 0011001 19 1 C#
    26 0011010 1A 1 D
    27 0011011 1B 1 D#
    28 0011100 1C 1 E
    29 0011101 1D 1 F
    30 0011110 1E 1 F#
    31 0011111 1F 1 G
    32 0100000 20 1 G#
    33 0100001 21 1 A
    34 0100010 22 1 A#
    35 0100011 23 1 B
    36 0100100 24 2 C
    37 0100101 25 2 C#
    38 0100110 26 2 D
    39 0100111 27 2 D#
    40 0101000 28 2 E
    41 0101001 29 2 F
    42 0101010 2A 2 F#
    43 0101011 2B 2 G
    44 0101100 2C 2 G#
    45 0101101 2D 2 A
    46 0101110 2E 2 A#
    47 0101111 2F 2 B
    48 0110000 30 3 C
    49 0110001 31 3 C#
    50 0110010 32 3 D
    51 0110011 33 3 D#
    52 0110100 34 3 E
    53 0110101 35 3 F
    54 0110110 36 3 F#
    55 0110111 37 3 G
    56 0111000 38 3 G#
    57 0111001 39 3 A
    58 0111010 3A 3 A#
    59 0111011 3B 3 B
    60 0111100 3C 4 C
    61 0111101 3D 4 C#
    62 0111110 3E 4 D
    63 0111111 3F 4 D#
    64 1000000 40 4 E
    65 1000001 41 4 F
    66 1000010 42 4 F#
    67 1000011 43 4 G
    68 1000100 44 4 G#
    69 1000101 45 4 A
    70 1000110 46 4 A#
    71 1000111 47 4 B
    72 1001000 48 5 C
    73 1001001 49 5 C#
    74 1001010 4A 5 D
    75 1001011 4B 5 D#
    76 1001100 4C 5 E
    77 1001101 4D 5 F
    78 1001110 4E 5 F#
    79 1001111 4F 5 G
    80 1010000 50 5 G#
    81 1010001 51 5 A
    82 1010010 52 5 A#
    83 1010011 53 5 B
    84 1010100 54 6 C
    85 1010101 55 6 C#
    86 1010110 56 6 D
    87 1010111 57 6 D#
    88 1011000 58 6 E
    89 1011001 59 6 F
    90 1011010 5A 6 F#
    91 1011011 5B 6 G
    92 1011100 5C 6 G#
    93 1011101 5D 6 A
    94 1011110 5E 6 A#
    95 1011111 5F 6 B
    96 1100000 60 7 C
    97 1100001 61 7 C#
    98 1100010 62 7 D
    99 1100011 63 7 D#
    100 1100100 64 7 E
    101 1100101 65 7 F
    102 1100110 66 7 F#
    103 1100111 67 7 G
    104 1101000 68 7 G#
    105 1101001 69 7 A
    106 1101010 6A 7 A#
    107 1101011 6B 7 B
    108 1101100 6C 8 C
    109 1101101 6D 8 C#
    110 1101110 6E 8 D
    111 1101111 6F 8 D#
    112 1110000 70 8 E
    113 1110001 71 8 F
    114 1110010 72 8 F#
    115 1110011 73 8 G
    116 1110100 74 8 G#
    117 1110101 75 8 A
    118 1110110 76 8 A#
    119 1110111 77 8 B
    120 1111000 78 9 C
    121 1111001 79 9 C#
    122 1111010 7A 9 D
    123 1111011 7B 9 D#
    124 1111100 7C 9 E
    125 1111101 7D 9 F
    126 1111110 7E 9 F#
    127 1111111 7F 9 G
  • 【Bus World】第一巴士-284

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

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

    介绍

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

    历史

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