css-render
简介由 naive-ui 的作者维护,并且 naive-ui 也使用了该库
文档地址:https://css-render.vercel.app
特点它仅仅作为一个 css 生成器,有点像 scss 的 js 实现,在代码层面与组件没有关联性
作者也在文档中建议使用 css-render 开发组件库而不是应用
并且带有一个简单的插件系统,作者维护了一个 BEM 插件,naive-ui 的样式大部分都通过该库配合 BEM 插件构建
使用默认导入该库并初始化后,其 c 方法是核心
12import CssRender from 'css-render';const { c } = CssRender();
构建渲染对象c 方法可以传三个参数:
第一个参数是选择器,支持 & 语法选中父选择器;
第二个参数是该选择器的样式;
第三个参数是孩子样式,传递一个数组,数组项都为 c 方法执行的结果;第二个参数是可选的,可以在直接在第二个参数上传孩子样式数组
1234c('.cls', { color: ...
CSS in JS 简述
前言还记得第一次接触到 CSS in JS 是在 20 年在学校第一次尝试用 React 做东西的时候
我老喜欢 Material Design 了,上来做东西那必须是 material-ui(现在的 MUI)
文档里建议的 CSS 编写方式除了 less,scss 这两个主流的预处理器外,还有一个我从未听过的 JS 库: styled-components
当年的我并没有选择去学习了解 CSS IN JS 的东西,今天在看 naive-ui 源码时发现作者自己造了个轮子 css-render,我知道是时候来还债了
什么是 CSS IN JS就是字面意思,在 js 中编写 css 样式
优点优点很明显,你可以用想到的任何形式组织样式,非常灵活
可以轻松做到样式隔离
css 和页面组件的关系一目了然,不容易出现大量冗余无用的 css 样式,他人浏览项目时效率更高
方便重构或修改样式
跟随组件代码一同加载,用到的才载入,有效避免引入外部 css 时阻塞浏览器渲染的问题
缺点缺点也十分明显
学习成本高,市面上的实现五花八门,除了上面说的 styled-components 之外 ...
盒模型
基础盒模型各个区域的功能,由其边界决定,先上一张 MDN 文档的图
图里很明显有四个边界
Content edge - 内容边界
Padding edge - 内边距边界
Border edge - 边框边界
Margin edge - 外边距边界
正好对应了四个区域
Content area - 内容区域
Padding area - 内边距区域
Border area - 边框区域
Margin area - 外边距区域
盒模型还分为标准盒模型和替代盒模型
标准盒模型为默认值,box-sizing: content-box,width 和 height 表示内容区域(Content area)的宽高
替代盒模型为 IE 的盒模型,box-sizing: border-box,宽高计算有所不同,这边的宽度为 width = contentHeight + padding + border-size,高度同理
Content area由 内容边距 Content edge 限制,容纳元素**”真正的内容”**
真正的内容包括:文本、图像、视频播放器等等 ...
样式优先级
选择器优先级会根据选择器的类型、数量来进行优先级比较
选择器类型会根据选择器类型来决定优先级
优先级由高到低如下:
内联属性,即 style 属性上的样式
ID 选择器
类选择器、属性选择器、伪类
元素选择器、伪元素
:::caution
*,+,>,~, (空格),:not不会影响优先级
:::
优先应用拥有最高优先级选择器的样式,例如下面样式
123456#id .class { background-color: red;}.main .content .class { background-color: blue;}
第一个有 ID 选择器和类选择器
第二个只有类选择器
所以第一个优先级高,背景色为红色 red
选择器数量当选择器类型的优先级一致时,就要看最高优先级选择器的数量了
例如下面样式
123456div > section .class { background-color: red;}div .child .class { background-color: bl ...
广东马上信息科技
做教育服务的,从小初高到大专大学,都有客户,卖教学硬件和捆绑的软件,同时还提供很多 Sass 软件
此次面试有三个问题没回答好,复盘一下
第三题别被标题迷惑了,邪门的很!
React 中在 setTimeout 内调用 setState这是个非常常见的问题,一般会问为什么拿到的是旧值
这个面试官直接难度提上来一档,如果没研究过 React 原理,可能会吃哑巴亏
当时是这样的:
面试官:嗯看来你对 React 的理解是没有 Vue 那么深入
我:没看过 React 源码
面试官:我们没想过招多牛的人,没看过没关系
当然研究过也可能翻车,看完下面问题和复盘实操就懂了
调用三次 setState,该组件会重新渲染几次?在 setTimeout 内调用三次呢?
首先是正常的调用三次
1234567891011121314151617import React, { FC, useState } from 'react';const TestPage: FC = () => { let [count, setCount] = ...
CDN依赖注入插件
本文参考了:超硬核|带你畅游在 Webpack 插件开发者的世界
需求有时候我们需要从 CDN 而不是代码中引入依赖,webpack 提供了 external 字段供我们配置
该配置有一个缺点,设置为外部依赖后的包,不知道代码中有没有使用,以防万一我们需要在 index.html 中写 script 标签注入依赖,例如引入 lodash:
123456789101112<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>Webpack App</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!-- 从 CDN 引入了 lodash --> <script src="https://cdnjs.cloud ...
Vue3 源码阅读(7)- watch
watch 第三个参数可以传入 options 对象,对象中 flush 属性可以控制回调的更新时机,分别是组件更新前、组件更新后 和 同步触发
从这里得知该 api 与组件渲染有关联,所以其实现不在 @vue/reactivity 里,而是在 @vue/runtime-core 中
具体路径为 packages/runtime-core/src/apiWatch.ts
watch我们跳转到 watch 实现,可以发现其具体实现是 doWatch 方法
1234567891011121314export function watch<T = any, Immediate extends Readonly<boolean> = false>( source: T | WatchSource<T>, cb: any, options?: WatchOptions<Immediate>): WatchStopHandle { if (__DEV__ && !isFunction(cb)) { w ...
Vue3 源码阅读(6)- computed
计算属性大家肯定都很熟悉了
其内部实现依赖 effect,追踪到变化后重新计算结果,并且返回的是一个类似 ref 的玩意
其源码在 packages/reactivity/src/computed.ts
computed我们直接定位到方法,可以看到有好几种声明:
123456789101112131415161718// 只传 getterexport function computed<T>( getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ComputedRef<T>// 传一个对象,里面放有 getter 和 setterexport function computed<T>( options: WritableComputedOptions<T>, debugOptions?: DebuggerOptions): WritableComputedRef<T>// 实现export function computed<T&g ...
Vue3 源码阅读(5)- ref
ref个人感觉 ref 设计的有些一言难尽,我个人是能用 reactive 的地方绝不用 ref,使用心智负担有点高…解包的行为有点迷
我们看下 ref 的实现:
123export function ref(value?: unknown) { return createRef(value, false);}
发现调用了 createRef 这个工厂方法:
123456function createRef(rawValue: unknown, shallow: boolean) { if (isRef(rawValue)) { return rawValue; } return new RefImpl(rawValue, shallow);}
该方法先判断对象是否已经是 ref,是则直接返回其本身,否则返回一个 RefImpl 的实例
RefImpl该类是 ref 的具体实现
成员变量12345678class RefImpl<T> { private _value: T; pri ...
Vue3 源码阅读(4)- effect
effect 是 @vue/reactivity 包中另外一个非常重要的实现,watchEffect,watch,computed 都是基于这个实现的,该 api 是公开的但是并没有写入文档
effect 就是副作用的意思,其作用很容易理解,我放一段代码:
12345678910111213141516171819<script setup> import { reactive, watchEffect, effect } from 'vue'; const count = reactive({ value: 0 }); const hello = reactive({ string: 'hello' }); effect(() => console.log('count:', count.value, 'hello:', hello.string)); const add = () => { co ...