首页
统计
赞助
留言
关于
更多
友链
壁纸
直播
Search
1
Joe — 一款个人类型Typecho主题
35,293 阅读
2
Joe开源目录程序系统
13,310 阅读
3
Typecho自定义后台编辑器功能
8,894 阅读
4
Joe主题实现自动更新
7,957 阅读
5
Joe主题自定义搭配色教程
4,756 阅读
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
登录
Search
https://78.al
累计撰写
76
篇文章
累计收到
3,818
条评论
首页
栏目
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
页面
统计
赞助
留言
关于
友链
壁纸
直播
搜索到
76
篇与
HaoOuBa
的结果
2021-05-12
一行代码为你的博客添加灰色默哀色
html { filter: grayscale(1); } 今天是2021-05-12 星期三,汶川地震13周年,为了纪念在灾难中不幸去世的人,网站也可以变成哀悼色通过一行代码实现全站变灰教程在任意css文件、style标签内加上以下属性,即可实现html { filter: grayscale(1); }Joe主题添加教程外观设置 - 全局设置 - 自定义css,填写以下内容{callout color="#f0ad4e"}html { filter: grayscale(1); }{/callout}
2021年05月12日
916 阅读
9 评论
10 点赞
2021-05-12
npm升级package.json依赖包到最新版本
全局安装检查更新工具npm install -g npm-check-updates使用检查package.json中dependencies的最新版本ncu更新dependencies到新版本ncu -u更新全部到最新版本ncu -a
2021年05月12日
227 阅读
1 评论
1 点赞
2021-05-11
便携小空调源码
云空调,便携小空调,为你的夏日带去清凉!预览优势随时随地打开空调便携低功耗(使用 HTML CSS 而非 Canvas 绘制)静音操作简单安装便捷劣势没有风安装您可以快速为您的网站安装空调。<iframe height="740" src="https://ac.yunyoujun.cn"></iframe>源码下载隐藏内容,请前往内页查看详情项目启动指令# yarn dev yarn start # http://localhost:3000/ yarn build # ./build
2021年05月11日
2,673 阅读
135 评论
17 点赞
2021-04-11
ES6
模板字符串带标签的模板的字符串const name = 'tom' const gender = false // 通过标签函数,获取模板字符串传递进来的值,可以将这个结果进行处理,返回出去 function tagFn(str, name, gender) { console.log(str) console.log(name) console.log(gender) return '111' } const res = tagFn`hello, my name is ${name}, my sex is${gender}`字符串拓展方法判断字符串是否包含某个字符const msg = 'hello world' msg.includes('world') // true判断字符串是否以某个字符开头,或以某个字符结尾const msg = 'hello world' msg.startsWith('h') // true msg.endsWith('d') // trueReflect提供一套统一操作对象的API,例如,像下面操作一个对象const obj = { name: 'hi', age: 18 } // 判断某个属性是否在对象里 console.log('name' in obj) // 删除对象某个属性 console.log(delete obj.name) // 将对象的属性名提取成数组 console.log(Object.keys(obj))从上面的实现方法可以看出,操作一个对象,用的方法很乱,一下用 in 一下用 delete ,一下用Object上的方法,同样操作一个对象,没有统一性,换成用 Reflect 实现:const obj = { name: 'hi', age: 18 } // 判断某个属性是否在对象里 console.log(Reflect.has(obj, 'name')) // 删除对象某个属性 console.log(Reflect.deleteProperty(obj, 'name')) // 将对象的属性名提取成数组 console.log(Reflect.ownKeys(obj))Map数据结构有下面的一个例子,将 对象 作为另一个对象的键存入,但是实际打印结果不如所愿:const obj = {} obj[{ name: 'tom' }] = 'Tom' console.log(obj) // { [object Object]: "Tom" }无论传入什么数据当作属性名,都会强制转换成字符串,转换不了的会转换成 [object Object] ,而通过Map数据映射结构就没有这种问题const map = new Map() const tom = { name: 'tom' } map.set(tom, 'Tom') console.log(map.get(tom))SymbolSymbol 是一个基本数据类型,主要用于创建一个独一无二的值console.log(Symbol() === Symbol()) // false,永远不可能有两个相等的Symbol在没有Symbol之前,一个对象里面,很有可能会存入属性名相同的两个属性,例如// 例如这是一个全局公用的缓存对象 const cache = {} ... cache['file_cache'] = 'xxx' ... // 代码多了后,可能就不知道cache里面有个file_cache的缓存名,然后继续存入file_cache缓存名,此时就会将之前传入的缓存给覆盖掉,因此就可能会出现问题 cache['file_cache'] = 'ooo'将上方缓存改成 Symbol 去实现:// 例如这是一个全局公用的缓存对象 const cache = {} ... // 括号里的是对这个Symbol的描述 cache[Symbol('file_cache')] = 'xxx' ... cache[Symbol('file_cache')] = 'ooo' /* * * { * Symbol(file_cache): "xxx" * Symbol(file_cache): "ooo" * } * */Symbol 还可以作为对象的私有成员,让外界去无法访问var People = (function() { var name = Symbol("name"); class People { constructor(n) { //构造函数 this[name] = n; } sayName() { console.log(this[name]); } } return People; })();Symbol内置属性1、控制instanceof的返回值class Person { static [Symbol.hasInstance](params) { console.log(params) console.log("我被用来检测") return false } } let o = {} console.log(o instanceof Person)Symbol的一些补充1、创建的Symbol属性,永远 不相等console.log(Symbol() === Symbol()) // false2、注册全局的Symbol,注册全局的Symbol,接收一个字符串,如果不是字符串会转换成字符串,相同的字符串生成的全局Symbol会 相等const s1 = Symbol.for('s1') const s2 = Symbol.for('s1') console.log(s1 === s2) // true console.log(Symbol.for(true) === Symbol.for('true')) // true3、对象内的Symbol,通过传统的获取,是 获取不到 的const obj = { [Symbol('hi')]: 'hi', name: 'hello' } for(let key in obj) { console.log(key) // name } // 如果想获取Symbol,需要通过Object.getOwnPropertySymbols()方法 console.log(Object.getOwnPropertySymbols(obj))生成器 Generatorfunction *fn() { console.log(111) yield 100 console.log(222) yield 200 console.log(333) yield 300 } var g = fn() // 调用一次,执行一次 g.next() // 100 {value: 100, done: false}使用生成器实现一个自增的idfunction *createId() { let id = 1 while(true) { yield id++ } } var c = createId() c.next() // 1 c.next() // 2 c.next() // 3generator传参function *fn(arg) { console.log(arg) let one = yield 100 console.log(one) let two = yield 100 console.log(two) let three = yield 300 console.log(three) } var g = fn('arg') // 会传入到arg处 g.next() g.next('aaa') // 会传入到one的位置 g.next('bbb') // 会传入到two的位置 g.next('ccc') // 会传入到three的位置使用生成器实现迭代器let todos = { life: ['吃饭', '睡觉'], study: ['语文', '数学', '英语'], [Symbol.iterator]: function* () { const all = [...this.life, ...this.study] for (let item of all) { yield item } } } for (let item of todos) { console.log(item); }使用生成器实现按顺序调用 用户信息 -> 订单信息 -> 商品信息 接口function getUser() { setTimeout(() => { let data = '用户信息' iterator.next(data) }, 1000) } function getOrder() { setTimeout(() => { let data = '订单信息' iterator.next(data) }, 1000) } function getGoods() { setTimeout(() => { let data = '商品信息' iterator.next(data) }, 1000) } function* fn() { let user = yield getUser() console.log(user); let order = yield getOrder() console.log(order); let goods = yield getGoods() console.log(goods); } let iterator = fn() iterator.next()数组includes方法与indexOf的区别indexOf无法查找NaN的情况const arr = ['foo', NaN, null] arr.indexOf(NaN) // -1使用includes可以查找出const arr = ['foo', NaN, null] arr.includes(NaN) // trueclass中将属性挂载到实例身上class Person { name = '杜恒' say = function() { console.log(1) } }class中static关键字的作用static 关键字定义的属性,是属于类上面的,而不是实例化出来的对象上面class Person { static name = 'hello' } const p = new Person() console.log(p.name) // undefined console.log(Person.name) // helloObject.entries & Object.fromEntries将对象转换成二维数组const obj = { name: '杜恒', age: 23 } const res = Object.entries(obj) console.log(res) // [ ["name", "杜恒"], ["age", 23] ]将二维数组、Map转换成普通对象const map = new Map() map.set("name", "杜恒") map.set("age", 23) console.log(map) const res = Object.fromEntries(map) console.log(res)Promise.allSettledPromise.allSettled用于接收一个数组, 与Promise.all很像,但是Promis.all是所有结果为成功状态,才返回成功。而Promise.allSellted是无论有没有失败情况下,都返回成功globalThis无论在什么环境下,globalThis都指向全局对象
2021年04月11日
691 阅读
18 评论
5 点赞
2021-04-08
TypeScript
TypeScript快速上手想使用 TypeScript ,需要先安装 Typescript ,安装命令(全局):npm i typescript -gTypeScript是渐进式的,无需懂TypeScript的语法,也可以使用,书写完代码,讲 *.ts 文件编译成普通能识别的 *.js 文件命令:tsc hello.ts原始数据类型const a: string = 'a'; const b: number = 1; // NaN Infinite const c: boolean = true; // false const d: null = null; const f: undefined = undefined; const g: void = undefined; // 联合类型 let a: number | string;unknown & anylet a: any; let b: string; // 将一个any类型赋值给其他类型,允许赋值 b = a; // √ let c: unknown; c = 'asdasd'; // unknown类型不能赋值给其他类型 b = c; // × // 如果就想要把c赋值给b,需要用到以下方式 // 第一种 if(typeof c === "string") b = c // 第二种,类型断言 (<类型>变量) 就相当于 (变量 as 类型) b = <string>c b = c as stringTypeScript中object类型在 typescript 中,定义变量为 object 不仅仅是对象,它表示除原始数据类型的数据,例如函数、数组等const obj1: object = () => {}; const obj2: object = []; const obj3: object = {};而在定义真正对象的时候,可以使用 字面量 方式或 接口 的方式const obj: { age: number; } = { age: 18 };数组类型定义一个变量为数组类型,有两种方式const arr1: Array<number> = [1, 2, 3]; const arr2: number[] = [1, 2, 3]; // demo function sum(...args: number[]) { return args.reduce((prev, current) => prev + current, 0); } sum(1, 2, 3);元组类型const user: [string, number] = ['Joe', 18]; const [_name, _age] = user; // demo const obj = Object.entries({ name: 'Joe', age: 18 }); console.log(obj); // obj返回的就是元组类型枚举类型定义一个枚举使用 enum 关键字,定义后不可以在修改enum STATUS { SUCCESS = 0, FAIL = 1, UNKNOW = 3 } console.log(STATUS.SUCCESS);上方这种方式编译后,会将 STATUS 编译成一个变量,可能会影响到代码的使用,如果不想编译成常量,需要再 enum 前面加上 const 关键字const enum STATUS { SUCCESS = 0, FAIL = 1, UNKNOW = 3 } console.log(STATUS.SUCCESS);函数类型1、函数声明式, ? 表示该值是可有可无的function fn1(a: number, b?: number): number { return 1; } fn1(1);2、函数表达式const fn2 = function (...args: number[]): number { return 1; }; fn2();3、没有返回值function fn3() :void {} fn3();任意类型function stringify(val: any): any { return JSON.stringify(val); } stringify(true);类型断言类型断言有两种方式,第一种方式是采用 as 关键字let _el = document.querySelector('.img'); let el = _el as HTMLImageElement; el.width = 100;第二种方式let _el = <HTMLImageElement>document.querySelector('.img'); _el.width = 1;接口接口的基本使用interface Post { title: string; content: string; } function getDetail(post: Post) { console.log(post.title); console.log(post.content); } getDetail({ title: '1', content: 'aaa' });接口可选属性interface Post { title: string; content: string; summary?: string; } const obj: Post = { title: '11', content: 'asdasd' };接口的动态属性interface Post { title: string; content: string; summary?: string; [key: string]: number | string; } const obj: Post = { title: '11', content: 'asdasd', test: 1 };类class User { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } sayHi(msg: string): void { console.log(`i am ${this.name}`); } }类里面的修饰符class User { // 默认为public public name: string; // 只允许在当前类访问 private age: number; // 只允许在当前和子类访问 protected sex: boolean; // 属性只读,定义后,不能再修改 readonly hobby: string = 'Rap'; constructor(name: string, age: number) { this.name = name; this.age = age; this.sex = true; } sayHi(msg: string): void { console.log(`i am ${this.name}`); } } const Tom = new User('Tom', 18);类与接口interface Eat { eat(food: string): void; } interface Run { run(): void; } // Person去实现 Eat 和 Run 接口 class Person implements Eat, Run { eat(food: string): void {} run() {} } class Animal implements Eat { eat() {} }抽象类abstract class Animal { eat(food: string): void {} abstract run(): void; } class Dog extends Animal { run() {} } // dog会有父类的eat方法,也会有自身的run方法 const dog = new Dog();泛型在定义时,不去指定具体的类型,在调用时,再把类型传递过去// 实现生成数字类型的数组 function createNumberArray(length: number, value: number): number[] { return Array<number>(length).fill(value); } createNumberArray(3, 1); // 实现生成字符串类型的数组 function createStringArray(length: number, value: string): string[] { return Array<string>(length).fill(value); } createStringArray(3, ''); // 利用泛型,根据传递的值,去实现不同的返回类型 function createArray<T>(length: number, value: T): T[] { return Array<T>(length).fill(value); } createArray(3, 1); createArray(3, '');类型声明有时候引入的第三方模块,没有使用类型定义,此时就需要自己去定义类型import { camelCase } from 'lodash'; declare function camelCase(input: string): string; const str = camelCase('asdJdf');
2021年04月08日
559 阅读
6 评论
6 点赞
2021-03-29
简单剖析jQuery源码
(function (global, factory) { /* * * CommonJS 规范 * 用于执行传递进来的factory函数 * */ if (typeof module !== 'undefined' && typeof module.exports === 'object') { /* * * 当前是 nodejs 环境 * */ // .... } else { /* * * 当前是浏览器环境 * 浏览器环境直接执行factory函数 * */ factory(global); } })(typeof window !== 'undefined' ? window : this, function (window, noGlobal) { /* * * 返回一个jQuery出去 * 使其能够链式操作 * */ jQuery = function (selector, context) { return new jQuery.fn.init(selector, context); }; /* * * jQuery共有原型空间 * */ jQuery.fn = jQuery.prototype = { jquery: '1.0.0', constructor: jQuery, /* * * 将init返回出的对象改成数组 * */ splice: [].splice }; init = jQuery.fn.init = function (selector) { var list = document.querySelectorAll(selector); [].push.apply(this, list); }; /* * * init与jQuery共享同一个原型(空间) * */ init.prototype = jQuery.fn; /* * * noGlobal不存在时 * 表示当前环境是浏览器 * 给window挂上$ * */ if (!noGlobal) { window.$ = window.jQuery = jQuery; } return jQuery; });
2021年03月29日
484 阅读
4 评论
10 点赞
2021-03-14
记录2021/03/13买的小猫咪
本来一直想养条狗的,但是狗需要遛,上班没有时间溜,于是去宠物店买了只猫回来,品种是淫贱层。
2021年03月14日
1,217 阅读
37 评论
40 点赞
2021-03-09
TypeScript
Typescript的基本使用Typescript的安装,通过npm全局安装Typescriptnpm install typescript -g编译Typescript的文件,typescript的文件以ts文件格式结尾,需要借助编译器编译成js文件后才可以运行,编译指令tsc xxxx.ts通过上面的方式编译,比较繁琐,因此都会在项目根目录中新建一个 tsconfig.json 的配置文件,用于设置ts文件的编译方式等{ /* * * 包含的路径 * ** 所有目录,包括子目录, * 所有文件 */ "include": ["./src/**/*"], /* * * 不需要被编译的文件目录 * */ "exclude": [], /* * * 编译选项 * */ "compilerOptions": { /* 编译后的目标兼容版本 */ "target": "ES6", /* 模块化规范 */ "module": "ES6", /* 打包后目录 */ "outDir": "./dist", /* 是否编译JS文件 */ "allowJs": false, /* 是否检查JS代码语法规范 */ "checkJs": false, /* 是否移除注释 */ "removeComments": false, /* 不生产编译后的文件 */ "noEmit": false, /* 当有错误时,不生产编译后的文件 */ "noEmitOnError": true, /* 设置编译后的文件为严格模式 */ "alwaysStrict": true, /* 不允许隐式的any类型 */ "noImplicitAny": true, /* 不允许不明确类型的this */ "noImplicitThis": true, /* 严格检查空值 */ "strictNullChecks": true, /* 开启全部严格检查 */ "strict": true // ... } }Typescript的基本语法定义变量的基本类型// 定义数字类型 const num: number = 1; // 定义字符串类型 const str: string = 'joe'; // 定义布尔值类型 const bool: boolean = true注意:null 和 undefined 有且只有1个值,因此声明变量为 null 或 undefined 后就不能再进行赋值操作let _test1: null; let _test2: undefined; _test1 = 1; // × _test2 = 1; // ×如果声明了一个变量,但是没有为这个值赋值,那么这个值默认为 undefinedlet num: number; // num的值为undefined如果既没有声明类型,也没有赋值,那么这个值默认为 any 类型let num; // num被推导为any类型null 和 undefined 在某些情况下,会有隐藏的问题。例如let num: num = 1; num = null; num.toFixed(2); // 这种情况下,编辑器不会报错,但是实际运行是有问题的为了避免出现上面的情形,就需要对 null 和 undefined 开启严格检查模式,开启方式是在 tsconfig.json 文件内加入一行{ "compileOptions": { ... // 设置严格检查 "strictNullChecks": true } }基本类型类型的包装类型在上面定义基本变量的时候,: 后面跟的类型都为小写,小写表示这是一个基本类型的数据,如果大写,那么它表示为基本类型的包装类型,例如let str: string = 'joe' // 定义一个基本类型的字符串 str = new String("1") // × new 出来的字符串,就是个包装类型,不能赋值给简单类型定义变量为对象类型对象内的属性比较少的时候,直接写成行内式const obj: {x: number; y: string} = { x: 1, y: 'joe' }对象内的属性如果多的时候,写成 接口 式// 使用 interface 关键字定义接口 interface MyObject { x: number; y: string; // 任意类型 [prop: string]: any; } // 对象使用接口 const obj: MyObject { x: 1, y: 'joe' }定义变量为数组类型typescript中数组的存储类型必须一致,所以在标注数组类型时,同时要标注数组中存储的数据类型let arr: Array<number> = [1, 2, 3]; // 简写形式:let arr: number[] = ... arr.push('11'); // 错误 arr.push(22); // 正确定义变量为元组类型元组类似数组,但是初始化的个数及对应位置,需要和标注的一致,并且越界数据,必须是标注中的类型之一let arr: [string, number] = ['hello', 2]; arr.push('1'); // 正确 arr.push(1); // 正确 arr.push(true); // 越界数据类型错误定义枚举类型enum HTTP_CODE { SUCCESS = 200, ERROR = 201, URL } HTTP_CODE.URL; // 202枚举类型的注意点:key不能是数字value可以是数字,称为数字类型枚举,如果没有值默认是0枚举值可以省略,如果省略,则:第一个枚举值默认0非第一个枚举值为上一个数字枚举值 + 1枚举值为只读(常量),定义后不可以被修改定义任意类型有时候并不确定这个值到底是什么类型,就可以标注为 any 类型const a: any = 1;any 类型的注意点:一个变量申明了未赋值且未标注情况下,默认为 any任何类型值都可以赋值给any类型any类型有任意属性和方法标注为any类型,意味着放弃对该值的类型检查,同时也放弃了编辑器的提示定义unknow类型unknow类型属于安全版的any类型。例如,由于any可以赋值给任意类型,下面的demo,会报错,并且无法检查到let a: any = '1'; let b: number = 1; b.toFixed(2); b = a; // 无法检测出 b.toFixed(2);换成 unknow 类型let a: unknown = '1'; let b: number = 1; b.toFixed(2); b = a; // 报错。不能将unknow类型赋值给其他类型 b.toFixed(2);使用 unknow 的注意点:unknow类型只能赋值给unknow、anyunknow类型没有任何属性和方法定义函数无返回值类型表示没有任何数据的类型,通常用于标注无返回值函数的返回值类型,函数默认标注类型为 voidfunction fn():void { console.log("joe") }定义函数为never类型当一个函数永远不可能执行 return 的时候,返回的就是 never,与 void 不同,void是执行了 return ,只是没有值,never是不会执行 return,比如抛出错误,导致函数终止执行function fn(): never { throw new Error('error'); }定义函数类型的返回值函数类型可以标注返回值类型、参数的类型,例如function fn(x: number): number { return x; }接口的使用接口的基本使用interface Point { x: number; y: number; } const point: Point = { x: 1, y: 1 }接口可选属性接口可以定义可选的属性,使用 ? 进行标注, ? 表示该值是可选的interface Point { x: number; y: number; z?: string; }接口属性只读接口可以定义只读的属性,使用 readonly进行标注,标注后,表示该属性值不可被修改inteface Point { readonly x: number; readonly y: number; } const point: Point = { x: 1, y: 2 }接口任意类型interface Point { x: number; y: string; [key: string]: any; } const point = { x: 1, y: 'hello', z: 1 }通过接口描述函数// 通过接口定义 interface Func { (e: Event): void; } const fn: Func = (e: Event) => {}; // 直接定义 function fn(el: HTMLElement, callback: (e: Event) => number) {} const div = document.querySelector('div'); fn(div, function () { return 1; });接口重名合并如果写了2个重名的接口,会将这2个接口进行合并interface Point { x: number; y: number; } interface Point { z: string; } const point: Point = { x: 1, y: 1, z: '11' };联合类型如果一个变量可以使用多个类型,可以使用 | 进行分割表示或function fn(el: HTMLElement, attr: string, value: string | number) {} const div = document.querySelector('div'); fn(div, 'a', 1);交叉类型interface O1 { x: number; } interface O2 { y: number; } const o: O1 & O2 = Object.assign({}, { x: 1 }, { y: 2 });注意:上面会报错,说Object上面没有assign方法,此时只需要在tsconfig.json中,添加es的lib库即可解决{ "compilerOptions": { ... "lib": ["ES6"] } }字面量类型在实际使用中,经常会有这种情况,只允许接受几个固定的值,其他的值不允许接受时,就可以使用字面量类型function fn(direction: 'left' | 'right') {} fn('left');类型别名继续上方的字面量类型,如果字面量类型的值过多,此时就应当使用类型别名// 普通使用 type direction = 'left' | 'right'; function fn(direction: direction) {} fn('left'); // 定义函数 type fn = (a: number) => number类型推导在实际开发中,每次定义变量,参数等都要写这些类型,很是麻烦,于是就有了类型推导,会自动根据上下文代码进行推导出类型const a = '111' // 此时,a的类型会自动认定为字符串类型类型断言默认的类型推导范围可能比较广,如果需要缩小范围,就需要使用类型断言const img = <HTMLImageElement>document.querySelector('img'); if (img) { img.src = ''; }函数标注函数标注有以下几种方式/* 第一种 */ function fn(a: number): number { return 1; } fn(1); /* 第二种 */ const fn2: (a: number) => number = function (a) { return 1; }; fn2(2); /* 第三种 */ type CallBack = (num: number) => number; const fn3: CallBack = function (num) { return 1; }; fn3(1); /* 第四种 */ interface Fn { (num: number): number; } let fn4: Fn = function (num) { return 1; }; fn4(2);可选参数function fn(el: HTMLElement, attr: string, val?: number) {} fn(document.querySelector('div'), 'width', 1);参数默认值function fn(attr: 'left' | 'right' = 'left') {} fn('left');剩余参数interface Rest { [key: string]: any; } function fn(target: Array<number>, ...rest: Array<Rest>) {} fn([1]);函数中this标注方式interface T { x: number; fn:(x: number) => void } const obj: T = { x: 1, fn(this: T, x: number){ this.x } }函数重载例如有这样一个例子,以下函数中,第一个参数为dom元素,第二个参数为display或opacity,第三个参数为数字或字符串function setStyle(el: HTMLElement, attr: 'display' | 'opacity', val: 'block' | 'none' | number) { ... }上面的参数这样写没问题,但是想要实现传入display时,第三个值必须是block或none,于是就可以利用函数重载实现function fn(el: HTMLElement, attr: 'display', val: 'block' | 'none'): void function fn(el: HTMLElement, attr: 'opacity', val: number): void function fn(el: HTMLElement, attr: string, val: any){}类类的基本使用class Person { /* 定义在实例上的属性 */ name = '杜恒'; /* 定义在类上的属性 */ static age = 18; /* 定义在实例上的方法 */ static say() { console.log(1); } } const duHeng = new Person() console.log(duHeng) console.log(Person)类的构造器class Dog { name: string; age: number; /* 实例化对象时,会调用这个构造器函数 */ constructor(name: string, age: number) { /* this指向当前实例化出的实例 */ console.log(this); this.name = name; this.age = age; } } const WangCai = new Dog('旺财', 1); const XiaoBai = new Dog('小白', 2); console.log(WangCai); console.log(XiaoBai);在typescript中,定义类的静态属性,使用public关键字,使用后,会自动设置成参数,并且会赋值,上面的写法等同于下面的class Dog { constructor(public name: string, public age: number) { // ... } }类里面的属性修饰符class User { constructor( // 公开属性,默认public public host: number // 可以访问,但是不能修改 readonly id: number, // 只能在内部和子类访问,但是不能被外部修改 protected username: string, // 外部、子类都不可以访问,只有当前能够访问 private password: string ) { } } const user = new User(1, 'Joe', '123') user.id; // 可以访问 user.id = 1; // × 不可以被修改 user.username; // × 不可读 user.password; // × 不可读上面的password设置成私有属性后,外部不可以被访问修改,但是如果就想让外部读取和修改,就需要使用到 寄存器class User { constructor(private _password: string) {} // 用于设置私有属性密码 set password(newPassword: string) { this._password = newPassword; } // 用于获取私有属性密码 get password(): string { return '****'; } } const user = new User('1'); user.password = '111'; user.password类当中的静态成员type FileList = 'gif' | 'png' | 'jpg' class User { // static 定义的属性只存在于类中,不存在于实例中 static readonly FILE_LIST: Array<FileList> = ['gif', 'png'] }抽象类/* * * 声明成抽象的类,无法new这个类 * 抽象类就是专门用来被继承的类 * */ abstract class Component { constructor(public props: any) {} /* 如果声明了方法为抽象的,那么必须声明这个类也是抽象的 */ abstract render(): void; } class SonComponent extends Component { render() {} } new SonComponent(1);规范类,实现类继承多个接口interface Info { getInfo(): string; } class A implements Info { getInfo() { return ''; } }泛型很多时候,标注的具体类型不能确定,因此就需要使用到泛型interface Inter { length: number; } function fn<T extends Inter>(obj: T) { return obj.length; } fn('sdasd');const obj1 = { x: 1, y: 2 } const obj2 = { a: 1, b: 2 } function fn<T>(obj: T, k: keyof T) { return obj[k] } fn<typeof obj1>(obj1, 'x')interface Res<T> { code: number; message?: string; data: T; } interface data { name: string; age: number; } async function getData<U>(url: string) { let response = await fetch(url); let data: Promise<Res<U>> = await response.json(); return data; } (async function () { const res = await getData<data>('/user'); })();
2021年03月09日
650 阅读
2 评论
6 点赞
2021-03-08
CSS面试题,实现固定的布局
简单记录个css面试题,要求实现以下需求:有间隔,间隔相等,为15px无论删除增加 div.item 都不会影响排版实现方式随意开始认为这个问题应该挺简单,写了下发下有点摸不到头脑,最后想了下可以通过以下方式去实现:第一种:<style> * { box-sizing: border-box; } .box { display: grid; gap: 15px; grid-template-columns: repeat(2, 1fr); width: 30%; margin: 0 auto; border: 1px solid #ff6800; padding: 15px; } .item { height: 150px; background: coral; } .item:nth-child(3n) { grid-column: 1 / 3; } </style> <div class="box"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>第二种:<style> * { box-sizing: border-box; } .box { width: 30%; margin: 0 auto; display: flex; flex-wrap: wrap; border: 1px solid #ff6800; padding: 7.5px; } .item { background-color: #ff6800; height: 150px; width: 50%; border: 7.5px solid #ffff } .item:nth-child(3n) { width: 100%; } </style> <div class="box"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>如果你有其他种实现方案,欢迎在下方留言
2021年03月08日
702 阅读
3 评论
13 点赞
2021-03-06
Typecho安全小知识
1、开启评论来源页检查,这样如果来源不是当前网站,则会无法评论,防止利用post请求去刷评论2、评论设置 里 允许使用的HTML标签和属性 选项里务必不能填写 a 标签和 script标签,经测试,填写这2项标签后,可以直接评论xss执行js脚本例如 a 标签的:<a href="javascript:void(function() {$('body').remove()})()">点击删除整个网页</a>例如 script 标签的<script> window.location.href = 'https://78.al' </script>
2021年03月06日
3,219 阅读
25 评论
23 点赞
2021-03-04
WebPack
模块化静态模块:import * from '' 需要先预定好导出的内容动态模块:import() 动态去引入模块模块化分类:CMDAMDESM(ecma script modules)UMD(主要用来兼容多个环境间的模块化引入问题)const umd = function (root, factory) { if (typeof module === 'object' && typeof module.exports === 'object') { /* 当前为node.js环境 */ module.exports = factory(); } else if (typeof define === 'function' && define.amd) { /* 当前是AMD环境 */ define(factory); } else { /* 普通浏览器环境 */ root.lib = factory(); } };webpackwebpack.config.jsconst path = require('path'); const HtmlWebpackPlugin = require("html-webpack-plugin") module.exports = { // 模式 production development none 对不同的环境,做的优化处理 mode: '', // 单入口单出口 entry: 'index.js', output: { filename: 'chunk.js', path: path.resolve('dist') }, // 多入口单出口 entry: ['index.js', 'list.js'], output: { filename: 'chunk.js', // 默认输出路径 path: path.resolve('dist') }, // 多入口,多出口 entry: { index: './index.js', list: './list.js' }, output: { filename: '[name].js', path: path.resolve('dist') }, // webpack默认只能打包js文件,如果需要打包其他文件,那么需要安装loader module: { // 配置模块加载解析规则(loader) rules: [ { // 匹配规则 test: '\.txt$/', // 使用什么解析器 use: { loader: 'raw-loader', options: { // 打包后文件名 name: '[name].[ext]', // 打包后的位置 outputPath: './txt' } } } ] }, // 安装一些插件 plugins: [ new HtmlWebpackPlugin({ ... }) ] }
2021年03月04日
446 阅读
2 评论
3 点赞
2021-02-25
Joe — 一款个人类型Typecho主题
主题下载{card-default width="100%" label="主题下载"}1、QQ群下载:10112681452、GitHub下载(帮忙点个star):https://github.com/HaoOuBa/Joe3、如果有什么问题或者需要帮忙优先微信联系,QQ不回复,微信:_liiii{/card-default}主题描述{card-default width="100%" label="主题亮点"}1、整包仅1.3Mb,却实现超强功能,极其迅速的响应(在开发时,都是使用30000篇文章进行开发测试)2、全站变量名、类名统一规范,重在方便更多人参与二开与拓展3、主题开箱即用,没有任何复杂的操作,无需像其他主题去特意创建个分类等。4、主题首发Typecho独家Joe编辑器5、主题响应式布局,不依赖任何响应式框架,采用 Joe 独家响应式6、主题在一切可能暴露的接口上,屏蔽sql注入、xss攻击风险,提供安全保障7、内置超强视频功能、包含直播功能、全网影视功能、文章内插入视频功能8、主题SEO极致优化,Lighthouse SEO跑分彪满100分9、主题色彩全局公用、小白轻松直接修改整站自定义主题色10、主题内置代码高亮、无需借助任何插件、支持200种语言11、主题首发极强画图回复功能,为你的博客带来用户互动,不再像传统博客那样,仅限文字12、主题内置sitemap、百度推送、友联、回复可见等,无需依赖任何插件{/card-default}编辑器演示(编辑器持续更新)下面为主题演示,无需担心您不会怎么写、怎么实现、以下的内容,主题自带编辑器均已集成、直接 插 入即可文本加粗那个女孩子 气喘吁吁 的打电话和你说:我在跑步文本倾斜你问她为什么有 啪啪啪 的声音,她和你说:我是穿拖鞋跑步的文本删除你明白了,此刻的头上正顶着个 率帽子 绿帽子行内代码远上寒山石径斜,白云生处有人家。停车 坐爱 枫林晚,霜叶红于二月花。横线引用那女孩对你说:你还不如跳蛋。有序列表杜蕾斯(durex)的优点如下:耐久(durability)可靠(reliability)优良(excellence)无序列表一个女朋友二个女朋友三个女朋友...N个女朋友卒超链接百度一下,你就凉了图片预览3行3列的表格表头表头表头鸡头鸭头龟头鸡头鸭头龟头鸡头鸭头龟头代码块const obj = { name: 'hi', age: 18 } // 判断某个属性是否在对象里 console.log('name' in obj) // 删除对象某个属性 console.log(delete obj.name) // 将对象的属性名提取成数组 console.log(Object.keys(obj))输出解析HTML 颜色大小 插入一个时间点2021-04-17 20:46:02 星期六段落缩进、空格 有些男人就像烤面筋,外表黄黄的,身体圆圆的,说话柔柔的,无害,看上去还非常好吃。可当你吃下去,才知道他绵绵的,并无特别的味道,甚至到你吃完,你都不知道他是用什么做的。 ----李七毛《我们都不擅长告别》特殊符号★ ╊ ➻ Ω... 这里有很多,就不全部演示了,编辑器上有这个按钮,直接 插 入就行了emoji表情这里需要改下数据库的存储格式才支持emoji,这里我没改,演示不了,改的教程网上都有,也很简单图片表情::(花心) :@(喜极而泣) ::(阴险) ୧(๑•̀⌄•́๑)૭... 这里有很多,就不全部演示了,编辑器上有这个按钮,直接 插 入就行了任务未完成{ } 每天都是崭新的一天哦!每天都要开心哦!任务已完成{x} 今天断气嗝屁了。居中标题{mtitle title="牛鞭牛鞭"/}插入一个m3u8或mp4视频(主题自带播发器,你也可以在后台修改成你自己的播放器){dplayer src="https://cdn.jsdelivr.net/gh/renrenmi/m3u8/唐人街探案3.m3u8"/}插入bilibili视频{bilibili bvid="BV1Ui4y1P78R"/}网易云歌单{music-list id="6800335663" width="100%"/}网易云音乐{music id="1303046498" width="100%" /}多彩按钮下面的实现方式,无需去学习怎么实现,编辑器直接 插 入自定义自己想要的颜色 {abtn color="#409eff"/} 自定义图标,达6000+图标任你使用 {abtn icon="fa-bath"/}自定义圆角度数,最大17.5px {abtn radius="4px"/}搭配在一起任意使用 {abtn color="#409eff" icon="fa-bath" href="" radius="0" content=""/}便条按钮便条按钮不能自定义色彩,必须使用一个图标,其他的的和上面的多彩按钮一样{anote icon="" href="" type="secondary" content=""/}{anote icon="" href="" type="success" content=""/} {anote icon="" href="" type="warning" content=""/} {anote icon="" href="" type="error" content=""/} {anote icon="" href="" type="info" content=""/}彩色虚线{dotted startColor="#ff6c6c" endColor="#1989fa"/}自定义虚线颜色,支持任意颜色{dotted startColor="#1772e8" endColor="#4cd327"/}回复可见隐藏内容,请前往内页查看详情默认卡片自定义宽度的卡片{card-default width="80%"}{/card-default}嵌套其他内容的卡片{card-default label="" width=""}{anote icon="" href="" type="secondary" content=""/}<div></div>猪狗你{/card-default}消息提示{message type="success" content=""/}{message type="info" content=""/}{message type="warning" content=""/}{message type="error" content=""/}附件预览主题自带博客附件预览功能,访问地址:{anote icon="fa-link" href="https://as.js.cn/usr/themes/Joe/library/files.php" type="success" content="点击访问"/}进度条{progress percentage="" color="#ff6c6c"/}自定义颜色{progress percentage="30%" color="#3a9aee"/}标注{callout color="#f0ad4e"}标注内容{/callout}支持嵌入任意内容,及任意颜色{callout color="#ff6800"}表头表头表头表格表格表格表格表格表格表格表格表格<div> hello </div>{/callout}自定义外部音乐{mp3 url="http://mp4.ik123.com/Dj_www.ik123.com/2010//202102%2Fik123_2102A011.mp4?vsid=yd1c4ae18a70c9b3a159d652571fb100mp4&name=www.ik123.com" /}Tabs标签页{tabs}{tabs-pane label="标签一"}<div>啊哈哈哈哈我是大傻逼!</div>{/tabs-pane}{tabs-pane label="标签二"}啊啊啊啊啊!哦哦哦哦哦?哈哈哈哈哈!{/tabs-pane}{/tabs}卡片列表{card-list}{card-list-item} 列表一内容{/card-list-item}{card-list-item} 列表二内容{/card-list-item}{card-list-item} 列表三内容{/card-list-item}{card-list-item} 列表四内容{/card-list-item}{/card-list}时间轴{timeline}{timeline-item color="#19be6b"} 1.0.0版本正式上线{/timeline-item}{timeline-item color="#19be6b"} 更新2.0.0版本{/timeline-item}{timeline-item color="#ed4014"} 删库跑路{/timeline-item}{/timeline}点击复制链接:https://pan.baidu.com/s/14wKBhs4geqSLETvpYhxGZQ 提取码:{copy showText="点击复制" copyText="z451"/}复制这段内容后打开百度网盘手机App,操作更不方便哦描述性卡片{card-describe title="卡片描述"}卡片内容{/card-describe}跑马灯{lamp/}折叠面板{collapse}{collapse-item label="折叠标题一" open} 折叠内容一{/collapse-item}{collapse-item label="折叠标题二"} 折叠内容二{/collapse-item}{/collapse}云盘下载{cloud type="default" url="" password=""/}{cloud type="360" url="" password=""/}{cloud type="bd" url="" password="zk6f"/}{cloud type="ty" url="" password=""/}{cloud type="ct" url="" password=""/}{cloud type="wy" url="" password=""/}{cloud type="github" url="" password=""/}{cloud type="lz" url="" password=""/}宫格3列,间距15px的宫格{gird column="3" gap="15"}{gird-item}{/gird-item}{gird-item}{/gird-item}{gird-item}{/gird-item}{/gird}警告提示{alert type="info"}警告提示{/alert}{alert type="success"}警告提示{/alert}{alert type="warning"}警告提示{/alert}{alert type="error"}警告提示{/alert}注意事项!!!以上全部功能,都无需担心怎么实现,编辑器上有按钮,一键 深入 插入!!!
2021年02月25日
35,293 阅读
1245 评论
1,022 点赞
1
...
3
4
5
...
7