Skip to main content

· 12 min read

什么是 Knex.js ?

Knex.js 是一个流行的Node.js SQL查询构建器,它允许你使用JavaScript语言编写SQL查询,而无需直接编写SQL语句。它支持多种数据库,包括MySQL,PostgreSQL,SQLite和Microsoft SQL Server等。

使用Knex.js,你可以轻松地构建复杂的SQL查询,包括联接、子查询和聚合函数等。它还提供了一些方便的功能,如事务处理,批量插入和更新等,更多信息参考Knex.js Guide

下面是 Knex 的使用示例,使用 js 实现的 DSL 读写上与 SQL 非常相似。

const knex = require('knex')({ client: 'mysql' });

knex.select('*').from('users').limit(10).toSQL();

· 6 min read

在 Ant Design(简称 Antd) 组件库中弹窗的使用频率很高,Antd 提供的Modal组件一般用法如下:

import React, { useState } from 'react';
import { Button, Modal } from 'antd';

const App: React.FC = () => {
const [isModalOpen, setIsModalOpen] = useState(false);

const showModal = () => {
setIsModalOpen(true);
};

const handleOk = () => {
setIsModalOpen(false);
};

const handleCancel = () => {
setIsModalOpen(false);
};

return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal title="Basic Modal" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
</>
);
};

上面使用方式存在几个问题:

  1. 弹窗与所属组件的状态混在一起,容易依赖组件内部的状态,导致其他地方不易复用
  2. 使用时需要关注弹窗的渲染位置,并主动控制弹窗的显示和隐藏细节
  3. 弹窗内容的渲染时机不好控制(需要额外处理),例如实现仅当弹窗可见时,才动态加载内容

我认为一个好用的弹窗我认为应该具备几个特点:

  1. 支持命令式调用,类似window.alert()这种方式(使用方无需关注弹窗的声明位置)
  2. 支持与弹窗的双向交互,即提供参数控制弹窗的渲染,同时弹窗关闭时能从中获取所需数据(这个在表单场景常见)
  3. 弹窗的状态与其所在组件树隔离(避免状态污染)

Antd 提供的 Modal.method() 很好的处理了第 1 和 3 个问题,使用起来很简单,只需一行代码即可。

Modal.confirm({
title: '确认?',
content: <MyModalContent>,
onOk () {
// do something
}
})

但是Modal.method()并未解决第 2 个问题,其内容展示后就与当前上下文脱离联系了,为了实现所期望的弹窗,下面我尝试了几种封装方式,试图解决这个问题。

· 2 min read

本文主要记录个人站点 whinc.github.io 的搭建过程,以及后续的维护更新,可以看做是个人站点自身的一份 changelog

站点基于 Docusaurus 搭建,其提供了博客、文档(MDX)、React 单单页应用多种模式构建站点,可以满足大部分的个人定制化的需求。

· 11 min read

动机 & 目标

在基于 hash 模式的 web 单页应用中,经常需要读写 hash 中的查询参数,例如从 hash 查询参数中读取商品 ID。在 React 应用中,如果直接解析window.location.hash值,则 hash 变化时无法收到更新,你还需要监听hashchange事件来更新内部状态,这些繁琐的步骤可以封装成自定义 hooks,同时更进一步给参数加上自动类型解析和序列化,使其支持任意参数值类型(包括嵌套的 JSON 对象),全部这些功能仅需要一个简单的 hook 即可实现。

· 7 min read

介绍

根据维基百科的介绍,在计算机编程中 glob 模式表示带有通配符的路径名,例如在 bash 中查看文件列表:

$ls src/*.js
src/a.js src/b.js

它最初是贝尔实验室 Unix 系统上的一个名叫 glob 的命令(glob 是 global 的缩写),用于展开命令行中的通配符。后来系统提供了该功能的 C 语言库函数glob(),知名的 shell 解释器就使用了该接口,shell 脚本和命令行中使用的 glob 模式匹配功能便源自于此。

· 10 min read

本文介绍一些前端项目的通用配置及相关资源,以便你了解项目中常见配置的含义以及配置方式。

目录

  • .gitignore - 让 Git 提交时忽略文件
  • editorconfig - 让编辑器或IDEs保持一致的编码样式
  • husky - 使用 git hooks 触发动作
  • lint-staged - 对 git 暂存区匹配的文件执行动作
  • commitzen - 命令行交互式生成符合约定式提交规范的 commit message
  • commitlint - 确保 commit message 符合约定式提交规范
  • Prettier - 美化代码格式
  • ESLint - 检查 JS 代码质量
  • Stylelint - 检查 CSS 代码质量

· 10 min read

在单页应用如此流行的今天,曾经令人惊叹的前端路由已经成为各大框架的基础标配,每个框架都提供了强大的路由功能,导致路由实现变的复杂。想要搞懂路由内部实现还是有些困难的,但是如果只想了解路由实现基本原理还是比较简单的。本文针对前端路由主流的实现方式 hash 和 history,提供了原生JS/React/Vue 共计六个版本供参考,每个版本的实现代码约 25~40 行左右(含空行)。

· 12 min read

目录

  1. 单组件生命周期
  2. 父子组件生命周期
  3. 使用 keep-alive 后的单组件生命周期
  4. 使用 keep-alive 后的父子组件生命周期
  5. 小结

组件化思维现在已得到广泛的认可,Vue 是围绕组件化构筑起来的框架。相比传统命令式 DOM 操作需要手动检查和处理 DOM 变化,Vue 以组件为单位,使用响应式数据自动更新 DOM,在组件生命周期中处理数据和 DOM 变化的各个阶段。基于 Vue 构建的交互界面始于一个根组件,将组件有组织的层层嵌套形成一颗组件树构建起复杂的网页应用。组件层层嵌套后,组件的生命周期方法调用的顺序变得很重要,尤其在处理一些需要父子组件联动的场景。本文先分析单组件的生命周期方法的执行时机,再考虑存在父子组件时,组件生命周期方法的执行顺序变化。

· 2 min read

计算机语言很多,无论哪种语言编写代码时都会遇到变量命名、方法命名等问题,网上关于代码命名风格的讨论已经多到无法形容了,甚至成为了程序员的一种价值观。今天不讨论命名风格孰优孰劣,仅整理下已有的命名风格作为了解,方便相互之间沟通。

· 13 min read

redux 是什么?

redux 是一个前端状态管理库。

为什么要搞个状态管理库来增加复杂度和学习成本呢?这样讲没错,简单的项目用 redux 就是折腾自己,我也不建议你用,但是大一点项目,尤其是多人协作时,就完全是另一回事了。

随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state(状态)。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候?由于什么原因?如何变化?已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。

· 11 min read

前言

为了增强对 ES6 Promise工作方式的理解,我实现了一个自己的ES6Promise类,接口与 ES6 的Promise类一致(包含构造函数、thencatchresolvereject), 并且符合 Promise/A+ 规范(通过了规范的全部测试用例) 。下面从简单开始,一步步实现一个自己的Promise

下面是最终实现的ES6Promise使用示例:

import {ES6Promise} from './es6-promise'


let p1 = new ES6Promise((resolve, reject) => {
resolve(1);
});

let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(999);
}, 1000);
});

ES6Promise.resolve(1)
.then(value => value + 1, reason => reason)
.then(value => ES6Promise.reject(p2), reason => reason)
.catch((value) => console.log(value)); // 999

· 12 min read

基于 React 的 UI 组件库层出不穷,作为组件库很重要的一个功能就是实现主题换肤功能。通过组件库提供的主题定制接口,用户只需要修改一些组件的 UI 参数,就可以达到修改整个组件库样式。

目标:可定制性强,并且易学易用。