新手前端学typescript - 实战篇, 实现浏览器全屏(59行)

学习一门新的语言, 🚀最快速的方法还是看实战代码!

初学ts的时候, 大家都会问"有什么实际项目可以参考吗?".

好了! 满足大家的需求, 我计划定期用ts做一些业务常用小插件, 代码量尽量小(控制在🦕1kb以内), 方便大家阅读源码, 也方便大家有时间去实现一遍.

浏览器全屏

最近后台项目需要一个"全屏"的按钮, github了下, 发现都仅仅支持"开启全屏", 而没有"切换"/"监听全屏状态"等功能, 所以打算自己写一个(主要代码量不大, 嘿嘿).

写代码之前说说逻辑

所有现代浏览器(>IE11)都提供了"全屏"的api,只是不同浏览器有不同的api(基本就是前缀不同), 所以我们要做的就是判断浏览器, 然后执行正确的api.

  1. 判断当前浏览器支持的前缀, 比如"webkit".
  2. 根据前缀得出我们需要的4个api的名字.
  3. 通过api实现"全屏"/"退出"/"切换"/"监听".

代码

源码: github.com/any86/be-fu…

首先我发现ts自带的声明中, 对webkitmoz开头的这种api并没有声明类型, 所以我们需要自己补充一下. 不然ts会提示找不到对应的方法.

🔥 知识点: 在自己的.d.ts文件中可以对ts系统自带的interface进行声明合并(扩展).

// global.d.ts
interface HTMLElement {
    // 进入全屏
    webkitRequestFullscreen(options?: FullscreenOptions): Promise<void>;
    webkitRequestFullScreen(options?: FullscreenOptions): Promise<void>;
    msRequestFullscreen(options?: FullscreenOptions): Promise<void>;
    mozRequestFullScreen(options?: FullscreenOptions): Promise<void>;

    // 监听全屏
    onwebkitfullscreenchange: ((this: Element, ev: Event) => any) | null;
    onmozfullscreenchange: ((this: Element, ev: Event) => any) | null;
    MSFullscreenChange: ((this: Element, ev: Event) => any) | null;
}

interface Document {
    // 当前全屏的元素
    readonly webkitFullscreenElement: Element | null;
    readonly msFullscreenElement: Element | null;
    readonly mozFullScreenElement: Element | null;

    // 退出全屏
    webkitExitFullscreen(): Promise<void>;
    msExitFullscreen(): Promise<void>;
    mozCancelFullScreen(): Promise<void>;
}
复制代码

提示: requestFullscreen(options?: FullscreenOptions): Promise<void>;可以在node_modules/typescript/lib/lib.dom.d.ts中找到.

🔥 功能实现

功能其实很简单, 我都写了注释, 就不过分解读了, 好了看实现代码:

type RFSMethodName = 'webkitRequestFullScreen' | 'requestFullscreen' | 'msRequestFullscreen' | 'mozRequestFullScreen';
type EFSMethodName = 'webkitExitFullscreen' | 'msExitFullscreen' | 'mozCancelFullScreen' | 'exitFullscreen';
type FSEPropName = 'webkitFullscreenElement' | 'msFullscreenElement' | 'mozFullScreenElement' | 'fullscreenElement';
type ONFSCPropName = 'onfullscreenchange' | 'onwebkitfullscreenchange' | 'onmozfullscreenchange' | 'MSFullscreenChange';

/**
 * caniuse
 * https://caniuse.com/#search=Fullscreen
 * 参考 MDN, 并不确定是否有o前缀的, 暂时不加入
 * https://developer.mozilla.org/zh-CN/docs/Web/API/Element/requestFullscreen
 * 各个浏览器
 * https://www.wikimoe.com/?post=82
 */
const DOC_EL = document.documentElement;

let RFC_METHOD_NAME: RFSMethodName = 'requestFullscreen';
let EFS_METHOD_NAME: EFSMethodName = 'exitFullscreen';
let FSE_PROP_NAME: FSEPropName = 'fullscreenElement';
let ON_FSC_PROP_NAME: ONFSCPropName = 'onfullscreenchange';

if (`webkitRequestFullScreen` in DOC_EL) {
    RFC_METHOD_NAME = 'webkitRequestFullScreen';
    EFS_METHOD_NAME = 'webkitExitFullscreen';
    FSE_PROP_NAME = 'webkitFullscreenElement';
    ON_FSC_PROP_NAME = 'onwebkitfullscreenchange';
} else if (`msRequestFullscreen` in DOC_EL) {
    RFC_METHOD_NAME = 'msRequestFullscreen';
    EFS_METHOD_NAME = 'msExitFullscreen';
    FSE_PROP_NAME = 'msFullscreenElement';
    ON_FSC_PROP_NAME = 'MSFullscreenChange';
} else if (`mozRequestFullScreen` in DOC_EL) {
    RFC_METHOD_NAME = 'mozRequestFullScreen';
    EFS_METHOD_NAME = 'mozCancelFullScreen';
    FSE_PROP_NAME = 'mozFullScreenElement';
    ON_FSC_PROP_NAME = 'onmozfullscreenchange';
} else if (!(`requestFullscreen` in DOC_EL)) {
    throw `当前浏览器不支持Fullscreen API !`;
}

/**
 * 启用全屏
 * @param  {HTMLElement} 元素
 * @param  {FullscreenOptions} 选项
 * @returns {Promise}
 */
export function beFull(el: HTMLElement = DOC_EL, options?: FullscreenOptions): Promise<void> {
    return el[RFC_METHOD_NAME](options);
}

/**
 * 退出全屏
 */
export function exitFull(): Promise<void> {
    return document[EFS_METHOD_NAME]();
}

/**
 * 元素是否全屏
 * @param {HTMLElement}
 */
export function isFull(el: HTMLElement | EventTarget): boolean {
    return el === document[FSE_PROP_NAME]
}

/**
 * 切换全屏/关闭
 * @param  {HTMLElement} 目标元素
 * @returns {Promise}
 */
export function toggleFull(el: HTMLElement = DOC_EL, options?: FullscreenOptions): Promise<void> {
    if (isFull(el)) {
        return exitFull();
    } else {
        return beFull(el, options)
    }
}

/**
 * 当全屏/退出时触发
 * @param  {HTMLElement} 元素
 * @param  {(isFull: boolean) => void} 返回"是否全屏"
 */
export function watchFull(el: HTMLElement, callback: (isFull: boolean) => void) {
    const cancel = () => {
        el.onfullscreenchange = null;
    };

    const handler = (event: Event) => {
        if (null !== event.target) {
            callback(isFull(event.target));
        }
    }

    // 这里addEventListener不好使
    el[ON_FSC_PROP_NAME] = handler;

    return {
        cancel
    }
}
复制代码

源码: github.com/any86/be-fu…

🚀 typescript系列课程

如果你对ts感兴趣了, 欢迎看看我的基础教程.

第一课, 体验typescript

第二课, 基础类型和入门高级类型

第三课, 泛型

第四课, 解读高级类型

第五课, 命名空间(namespace)是什么

特别篇, 在vue3🔥源码中学会typescript🦕 - "is"

第六课, 什么是声明文件(declare)? 🦕 - 全局声明篇

总结

多写多练, 很快就上手, 放几个我用ts写的项目当做参考, 抛砖引玉, 加油!

✋ 移动/pc端手势库, 支持: tap/press/pan/swipe/rotate/pinch

github.com/any86/any-t…

🍭 把vue组件变成this.$xxx这样的命令

github.com/any86/vue-c…

🍔 任意元素全屏显示, 支持PC/移动端, 不到1kb

github.com/any86/be-fu…

微信群

感谢大家的阅读, 如有疑问可以加我微信, 我拉你进入微信群(由于腾讯对微信群的100人限制, 超过100人后必须由群成员拉入)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-typescript-import-dts 是一个用于为 Vue.js 项目中的 TypeScript 文件生成类型声明文件的工具。在 Vue.js 项目中使用 TypeScript开发时,我们经常需要为一些第三方库或自定义组件编写类型声明文件,以提供更好的代码提示和类型检查。 使用 vue-typescript-import-dts 工具可以自动分析 TypeScript 文件中的导入语句,并根据导入的模块生成对应的类型声明文件。这样,在使用该模块时,IDE 或编辑器就能提供准确的代码补全和类型检查。 例如,假设我们的项目中使用了一个名为 axios 的第三方库进网络请求,但是该库并没有提供类型声明文件。我们可以通过 vue-typescript-import-dts 工具,在我们的 TypeScript 文件中导入 axios,并正确配置工具,它将自动为我们生成一个 axios.d.ts 类型声明文件。 具体使用 vue-typescript-import-dts 的步骤如下: 1. 在项目中安装 vue-typescript-import-dts,可以使用 npm 或 yarn 命令来安装。 2. 在 TypeScript 文件中,使用 import 语句导入需要生成类型声明文件的模块。 3. 在项目根目录下创建一个 .vue-typescript-import-dts.json 配置文件,用来配置生成类型声明文件的规则。可以指定生成的声明文件的输出路径、文件名等。 4. 运 vue-typescript-import-dts 命令,它会自动扫描 TypeScript 文件中的导入语句,并根据配置生成相应的类型声明文件。 这样,在我们编写代码时,IDE 或编辑器就可以准确地为我们提供代码补全和类型检查的功能。这对于提高开发效率和代码质量非常有帮助。 总之,vue-typescript-import-dts 是一个便捷的工具,可以自动为 Vue.js 项目中使用的第三方库或自定义组件生成类型声明文件,提供更好的代码提示和类型检查功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值