朴一

朴一 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

朴一 发布了文章 · 2月23日

antd源码分析 gird

官方文档 https://ant.design/components...

目录

一、antd中的Grid

目录

  1. 整体思路
  2. less文件结构图(♦♦♦重要)
  3. less实现逻辑图(♦♦♦重要)
  4. 源码节选:antd/components/grid/style/mixin.less
  5. 源码节选:antd/components/grid/col.tsx

没有使用React 底层基础组件。Grid的特点在于css样式的控制,本次着重对css结构进行了梳理代码目录

1、整体实现思路

col

less负责生成 ant-col-1 到 ant-col-24 的样式

组件tsx中负责根据父组件传入的props属性,生成自己使用的class名称

row

处理不同size下处理整行宽度

处理间距gutter

2、css文件结构图

3、col中less实现逻辑图

4、源码节选:antd/components/grid/style/mixin.less

5、源码节选:antd/components/grid/col.tsx

二、其他源码解读

目录
1.responsiveObserve.js解读

  1. row.js解读

1、responsiveObserve.js文件

image.png
image.png

Window matchMedia() 方法的基本使用
matchMedia() 返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。
语法
window.matchMedia(mediaQueryString)
mediaQueryString: 必需,一个字符串,表示即将返回一个新 MediaQueryList 对象的媒体查询。
matchMedia() 方法的值可以是任何一个 CSS @media 规则 的特性, 如 min-height, min-width, orientation 等。

MediaQueryList 对象的属性和方法

属性:
media:查询语句的内容。
alert(window.matchMedia("(max-width:100px)").media); //(max-width: 100px)
matches:用于检测查询结果,如果文档匹配 media query 列表,值为 true,否则为 false。
方法:
addListener(_functionref_)
添加一个新的监听器函数,该函数在媒体查询的结果发生变化时执行。
removeListener(_functionref_)
从媒体查询列表中删除之前添加的监听器。 如果指定的监听器不在列表中,则不执行任何操作。

实例

判断屏幕(screen/viewport)窗口大小:
if (window.matchMedia("(max-width: 700px)").matches) {
    /* 窗口小于或等于 700 像素 */
} else {
    /*窗口大于 700 像素 */
}
判断屏幕(screen/viewport)窗口大小,在小于等于 700 像素时修改背景颜色为黄色,大于 700 像素时修改背景颜色为粉红色:
function myFunction(x) { 
 if (x.matches) { 
 // 媒体查询 
 document.body.style.backgroundColor = "yellow"; 
 } else { 
  document.body.style.backgroundColor = "pink"; 
 } 
} 
var x = window.matchMedia("(max-width: 700px)") 
myFunction(x) // 执行时调用的监听函数 
x.addListener(myFunction) // 状态改变时添加监听器

image.png

可选链操作符( ?. )的基本使用(https://wiki.developer.mozill...
可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。

原理
比如,思考一个存在嵌套结构的对象 obj。不使用可选链的话,查找一个深度嵌套的子属性时,需要验证之间的引用,例如:

let nestedProp = obj.first && obj.first.second;

为了避免报错,在访问obj.first.second之前,要保证 obj.first 的值既不是 null,也不是 undefined。如果只是直接访问 obj.first.second,而不对 obj.first 进行校验,则有可能抛出错误。

有了可选链操作符(?.),在访问 obj.first.second 之前,不再需要明确地校验 obj.first 的状态,再并用短路计算获取最终结果:

let nestedProp = obj.first?.second;

通过使用 ?. 操作符取代 . 操作符,JavaScript 会在尝试访问 obj.first.second 之前,先隐式地检查并确定 obj.first 既不是 null 也不是 undefined。如果obj.firstnull 或者 undefined,表达式将会短路计算直接返回 undefined

这等价于以下表达式,但实际上没有创建临时变量:

let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);

实例

const adventurer = {
  name: 'Alice',
  cat: {
    name: 'Dinah'
  }
};

const dogName = adventurer.dog?.name;
console.log(dogName);
// expected output: undefined

console.log(adventurer.someNonExistentMethod?.());
// expected output: undefined

2、row.js文件

(1)官网上的可传参数

(2)源码详解

image.png

classNames的基本用法
classNames是一个简单的js实用插件,它的主要用例之一是使动态和条件className道具更易于使用(尤其是比条件字符串操作更简单)。

使用时它将导出classNames方法,该函数接受任意数量的参数,这些参数可以是 字符串对象

classNames (' foo ',' bar ')  ; // =>'foo bar' 

classNames (' foo ',{ bar :true } )  ; // =>'foo bar' 

classNames ({ ' foo-bar ':true } )  ; // =>'foo-bar' 

classNames ({ ' foo-bar ':false } )  ; // =>'' 

classNames ({ foo :true } ,{ bar :true } )  ; // =>'foo bar' 

classNames ({ foo :true , bar :true } )  ; // =>'foo bar' 

// 许多不同类型的参数

classNames (' foo ',{ bar :true , duck :false } ,' baz ',{ quux :true } )  ; // =>'foo bar baz quux' 

// 其他虚假值将被忽略

classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'

结合es6的模板语法使用(gird组件中多用)

let buttonType = 'primary';

classNames({ [`btn-${buttonType}`]: true });

image.png

代码中的 Partial<>Record<> 都是ts里面的内置类型

1.keyof

keyofObject.keys 略有相似,只不过 keyofinterface 的键。

interface Point { x: number; y: number; }

type keys = keyof Point; // type keys = "x" | "y"
用例:
假设有一个 object 如下所示,我们需要使用 typescript 实现一个 get 函数来获取它的属性值。
一般情况下,我们会这样写:
const data = {
  a: 3,
  hello: 'world'
}

function get(o: object, name: string) {
  return o[name]
}
但这样有几个缺点
1.无法确定返回类型:这将损失ts最大的类型校验功能
2.无法对 key 做约束:可能会拼写错误
3.可做修改达到类型约束,但不够简洁

这时可以使用 keyof 来加强 get 函数的类型功能

function get<T extends object,k extends keyof T>(o:T,name:K):T[k]{
  return o[name]
}

2.partial

keyof T 拿到 T 所有属性名, 然后 in 进行遍历, 将值赋给 P, 最后 T[P] 取> > 得相应属性的值.
type Partial<T> = {
 [P in keyof T]?: T[P];
}; 
例子:
 interface People {name: string}
 // 变为
 Partial<People> => {name?: string}
 
 其是有局限性的,只能处理一层
 
 interface People {
  name: string;
  person: {name: string; name1: string}
 }
 type NewPeople = Partial<People>
 // error: Property 'name1' is missing in type ...
 const jack: NewPeople = {
  name: 'jack',
  person: {
  name: 'son'
  }
 }
 // 如何解决呢 递归
 type PowerPartial<T> = {
  [U in keyof T]?: T[U] extends object
  ? PowerPartial<T[U]>
  : T[U]
 };

3.record

标记对象的 key value类型
type Record<K extends keyof any, T> = {
 [P in K]: T;
};
例子:
const user: Record<'name'|'email', string> = {
 name: '', 
 email: ''
}

// 复杂一点
function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;

// 这里简易实现,否则报ts(2391)错误
function mapObject(): any {}

const names = { foo: "hello", bar: "world", baz: "bye" };

const lengths = mapObject(names, s => s.length); 

type newNames =  typeof lengths  // => { foo: number, bar: number, baz: number }

4.pick

这个类型则可以将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型。
type Pick<T, K extends keyof T> = {

 [P in K]: T[P]; 

};
例子:
interface User { id: number; age: number; name: string; };

// 相当于: type PickUser = { id: number; age: number; }

type PickUser = Pick<User, "id" | "age"> 

image.png

类型保护和类型断言

由于可以为null的类型是通过联合类型实现,那么你需要使用类型保护来去除 null。 幸运地是这与在JavaScript里写的代码一致:

function f(sn: string | null): string {
    if (sn == null) {
        return "default";
    }
    else {
        return sn;
    }
}

这里很明显地去除了 null,你也可以使用短路运算符:

function f(sn: string | null): string {
    return sn || "default";
}

如果编译器不能够去除 nullundefined,你可以使用类型断言手动去除。 语法是添加 !后缀: identifier!identifier的类型里去除了 nullundefined

function broken(name: string | null): string {
  function postfix(epithet: string) {
    return name.charAt(0) + '.  the ' + epithet; // error, 'name' is possibly null
  }
  name = name || "Bob";
  return postfix("great");
}

function fixed(name: string | null): string {
  function postfix(epithet: string) {
    return name!.charAt(0) + '.  the ' + epithet; // ok
  }
  name = name || "Bob";
  return postfix("great");
}

本例使用了嵌套函数,因为编译器无法去除嵌套函数的null(除非是立即调用的函数表达式)。 因为它无法跟踪所有对嵌套函数的调用,尤其是你将内层函数做为外层函数的返回值。 如果无法知道函数在哪里被调用,就无法知道调用时 name的类型。

查看原文

赞 0 收藏 0 评论 0

朴一 赞了回答 · 2020-12-23

解决element-ui select 多选框+checkbox 混合用遇到的问题

<el-select v-model="frequencyEditForm.weekCheckList" multiple>

 <el-option
    v-for="(item, index) in weekList"
    :key="index"
    :value="item.value"
    :label="item.label"
  >
   <span class="check"></span>
   <span style="margin-left: 8px">{{item.label}}</span>
  </el-option>
</el-select>


<style scoped>

.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{

content: "";

}

.el-select-dropdown.is-multiple .el-select-dropdown__item.selected .check{

background-color: #409eff;
border-color: #409eff;

}

.el-select-dropdown.is-multiple .el-select-dropdown__item.selected .check:after{

transform: rotate(45deg) scaleY(1);

}

.el-select-dropdown.is-multiple .el-select-dropdown__item .check::after{

box-sizing: content-box;
content: "";
border: 1px solid #fff;
border-left: 0;
border-top: 0;
height: 7px;
left: 4px;
position: absolute;
top: 1px;
transform: rotate(45deg) scaleY(0);
width: 3px;
transition: transform .15s ease-in .05s;
transform-origin: center;

}

.el-select-dropdown.is-multiple .el-select-dropdown__item .check{

display: inline-block;
position: relative;
top:2px;
border: 1px solid #dcdfe6;
border-radius: 2px;
box-sizing: border-box;
width: 14px;
height: 14px;
background-color: #fff;
z-index: 1;
transition: border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);

}
</style>

关注 6 回答 4

朴一 关注了专栏 · 2020-12-23

K8S生态

Container, Docker, Go, Kubernetes, Python, Vim; 微信公众号: MoeLove

关注 10588

朴一 关注了专栏 · 2020-12-23

springboot 最佳实践

SpringBoot技术的势、道、术分析与实践。

关注 10107

朴一 关注了专栏 · 2020-12-23

SegmentFault 行业快讯

第一时间为开发者提供行业相关的实时热点资讯

关注 58560

朴一 关注了专栏 · 2020-12-23

民工哥技术之路

公众号:民工哥技术之路、《Linux系统运维指南 从入门到企业实战》作者。专注系统架构、高可用、高性能、高并发,数据库、大数据、数据分析、Python技术、集群中间件、后端等开源技术分享。

关注 27335

朴一 关注了专栏 · 2020-12-23

concent

concent,一个内置依赖收集系统,并兼具0入侵、可预测、渐进式、高性能特点的react状态管理方案。

关注 9301

朴一 关注了专栏 · 2020-12-23

阿里云栖号

汇集阿里技术精粹-yq.aliyun.com

关注 15772

朴一 关注了专栏 · 2020-12-23

终身学习者

我要先坚持分享20年,大家来一起见证吧。

关注 51385

朴一 关注了专栏 · 2020-12-23

疯狂的技术宅

本专栏文章首发于公众号:前端先锋 。

关注 27204

认证与成就

  • 获得 0 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-12-23
个人主页被 105 人浏览