HTML5 中引入了 <dialog>
元素,它提供了一种简单的方式来创建对话框或模态框,用于与用户进行交互、显示信息或接收输入。
css view-transition
什么是 CSS View-Transition?
CSS View-Transition 是一种用于创建平滑过渡效果的 CSS 属性。它可以让元素在视图之间进行过渡,从而实现动画效果。通过使用 CSS View-Transition,我们可以在前端开发中创建各种各样的动态效果,提升用户体验。
如何使用 CSS View-Transition?
使用 CSS View-Transition 非常简单。我们只需要为目标元素添加一些必要的 CSS 属性即可。
- 首先,为目标元素添加
transition
属性,指定过渡的属性和持续时间。例如:
1 | .element { |
在上面的例子中,我们指定了 width
属性在 0.3 秒内进行过渡,并且使用了 ease-in-out
缓动函数。
- 接下来,我们可以通过添加一些触发事件来激活过渡效果。例如,我们可以使用鼠标悬停事件来触发过渡效果:
1 | .element:hover { |
在上面的例子中,当鼠标悬停在 .element
元素上时,它的宽度将过渡到 200 像素。
CSS View-Transition 的常用属性
除了 transition
属性外,CSS View-Transition 还提供了其他一些常用属性,用于进一步控制过渡效果。
transition-property
:指定过渡的属性。可以使用多个属性,用逗号分隔。transition-duration
:指定过渡的持续时间。transition-timing-function
:指定过渡的缓动函数。transition-delay
:指定过渡的延迟时间。
使用场景示例
1. 图片展示过渡
1 | <div class="image-container"> |
1 | .image-container { |
在上面的例子中,当鼠标悬停在图片上时,图片将以 1.2 倍的比例进行放大,创建出平滑的过渡效果。
2. 菜单项过渡
1 | <ul class="menu"> |
1 | .menu-item { |
在上面的例子中,当鼠标悬停在菜单项上时,背景颜色将以平滑的过渡效果变为灰色。
总结
CSS View-Transition 是一种非常强大的前端开发工具,可以帮助我们创建各种各样的动态效果。通过简单地添加一些 CSS 属性,我们就可以实现平滑的过渡效果,提升用户体验。
navigator.registerProtocolHandler
navigator.registerProtocolHandler
是一个 Web API,用于注册自定义协议处理程序。通过使用这个 API,您可以告诉浏览器如何处理特定的自定义协议,例如打开特定的应用程序或执行特定的操作。这对于创建与操作系统或其他应用程序集成的 Web 应用程序非常有用。
如何使用 navigator.registerProtocolHandler
:hammer_and_wrench:
使用 navigator.registerProtocolHandler
需要以下步骤:
确定自定义协议:首先,您需要确定您要注册的自定义协议。这个协议应该是唯一的,并且与其他现有的协议不冲突。例如,您可以选择
myapp
作为您的自定义协议。创建处理程序:接下来,您需要创建一个处理程序,用于处理您的自定义协议。这可以是一个本地应用程序、一个网页或一个特定的操作。处理程序应该能够接收来自浏览器的自定义协议请求,并做出相应的响应。
注册协议处理程序:使用
navigator.registerProtocolHandler
方法来注册您的自定义协议处理程序。该方法接受三个参数:协议名称、处理程序的 URL 和一个可选的标题。以下是一个示例:1
navigator.registerProtocolHandler('myapp', 'https://example.com/myapp-handler?url=%s', 'My App');
在上面的示例中,
myapp
是自定义协议的名称,https://example.com/myapp-handler?url=%s
是处理程序的 URL,My App
是可选的标题。测试协议处理程序:注册完成后,您可以测试您的协议处理程序是否正常工作。您可以尝试在浏览器中输入
myapp://example.com
(将example.com
替换为您的实际网址),并查看处理程序是否正确地响应。
示例应用场景 :bulb:
桌面应用程序集成:您可以使用
navigator.registerProtocolHandler
将您的 Web 应用程序与桌面应用程序集成。例如,当用户点击您的网页中的特定链接时,您可以打开您的桌面应用程序并传递相应的参数。自定义处理程序:您可以创建一个自定义的处理程序,用于处理特定的自定义协议。例如,您可以创建一个处理程序,用于处理邮件链接,并直接打开用户默认的邮件客户端。
支持的浏览器 :globe_with_meridians:
目前,navigator.registerProtocolHandler
在大多数现代浏览器中得到支持,包括 Chrome、Firefox 和 Safari 等。但是,不同浏览器对于自定义协议的支持程度可能有所不同,因此在使用时请注意兼容性。
结论 :memo:
navigator.registerProtocolHandler
是一个强大的 Web API,可以帮助您注册自定义协议处理程序,实现与操作系统或其他应用程序的集成。通过使用这个 API,您可以为您的 Web 应用程序带来更多的灵活性和功能性。在使用时,请确保考虑兼容性,并进行充分的测试,以确保您的协议处理程序正常工作。
希望本文对您理解和使用 navigator.registerProtocolHandler
有所帮助!:sparkles:
面试题合集
HTML + CSS
- 什么是 BFC ?如何触发?有何特点?如何解决 margin“塌陷”?
- CSS 如何出来溢出?说一下 overflow 不同值的区别。
- 三栏布局有什么实现方式?
- css calc 属性作用是什么?主要用于解决什么问题?
- 有一个固定长宽div,怎么实现在屏幕上垂直水平居中
- 描述一下渐进增强(progressive enhancement)和优雅降级(graceful degradation)
- iframe 有哪些优点?哪些缺点?用它来解决过什么问题?
- Google Chrome 如何支持大小小于 12px 的文字?
- 描述一下 css 盒子模型
- HTML5 的特性有哪些?
- CSS3 的特性有哪些?
- 如何实现水平居中?
- 如何实现垂直居中?
- 如何实现双圣杯布局?
- CSS 中选择器的优先级?
- CSS 权重如何计算?
- HTML5 input 元素 type 属性有哪些?
- CSS 中哪些属性可继承,哪些不可以
- CSS 单位中 px、em 和 rem 的区别?配合 font-size 如何计算?(移动端适配方案)
- 如何画一条 0.5px 的线
- 隐藏一个元素有哪些方法?display: none 与 visibility: hidden 与 opacity: 0 之间的区别?
- position 的值有哪些,分别有什么特点?
- 什么是浮动,浮动会引起什么问题,有何解决方案?
- line-height 和 height 的区别
- 设置一个元素的背景颜色,背景颜色会填充哪些区域?
- inline-block、inline 和 block 的区别;为什么 img 是 inline 还可以设置宽高
- 什么是重绘?什么是回流?如何减少?如何让文档脱离文档流?
- box-sizing 的作用,如何使用?
- 如何实现清除浮动
- css 动画如何实现
- 如何实现在某个容器中居中的?
- 如何改变一个 DOM 元素的字体颜色?
- 相对布局和绝对布局,position:relative 和 obsolute。
- 什么是弹性盒子 flex 布局?
- 什么是 rem 布局?
- less 和 scss 有什么区别?
- ::before 和::after 中双冒号和单冒号的区别?
- CSS3 新增伪类,以及伪元素?
- 响应式布局实现方案?
- link 标签和 import 标签的区别?
- transition 和 animation 的区别?
- 说一下块元素、行元素、置换元素
- 多行元素的文本省略号如何实现?
- Doctype 作用? 严格模式与混杂模式如何区分?它们有何意义?
Javascript
- javascript 的数据类型有哪些?
- javascript 有哪些引用类型?
- 如何判断 javascript 的数据类型?
- 怎么判断两个对象相等?如何判断空对象?
- 0.1 + 0.2 为什么不等于 0.3 ?(解释原理)
- 强制类型转换、隐式类型转换分别是什么,列举场景说明。
- 创建函数的几种方式?
- javascript 创建对象的几种方式?
- 列举宿主对象、内置对象、原生对象并说明其定义。
- === 和 ==的区别?
- null,undefined 的区别
- 什么情况下会返回 undefined 值?
- 如何区分数组和对象?
- 多维数组如何降维?
- 怎么获取当前日期(年-月-日 时:分:秒)?
- 什么是类数组(伪数组),如何将其转化为真实的数组?
- 如何遍历对象的属性?
- 如何给一个按钮绑定两个 onclick 事件?
- 变量提升是什么?与函数提升的区别?
- 什么是作用域链?如何延长?
- 如何实现数组的随机排序?
- dom 节点的 Attribute 和 Property 有何区别?
- dom 结构操作怎样添加、移除、移动、复制、创建和查找节点?
- 什么是事件冒泡,它是如何工作的?如何阻止事件冒泡?
- 什么是事件捕获,它是如何工作的?
- 如何让事件先冒泡后捕获?
- JavaScript 动画和 CSS3 动画有什么区别?
- dom 的事件模型
- 事件三要素是什么?
- 获取元素位置?
- 如何绑定事件,如何解除事件?
- 对事件委托的理解
- setTimeout 和 setInterval 的区别及用法是什么?
- 用 setTimeout 来实现 setInterval
- document.write 和 innerHTML 的区别?
- 元素拖动如何实现,原理是怎样?
- 什么是重绘(repaint)?什么是回流(reflow)?如何最小化重绘和回流?
- 延迟加载的方式有哪些?
- 垃圾回收机制有哪些?具体怎么如何执行?
- 什么是内存泄漏 ?
- 数组遍历的方法有哪些,分别有什么特点,性能如何 ?
- ES5 和 ES6 的区别,ES6 新增了什么?
- ES6 的继承和 ES5 的继承有什么区别?
- var、let、const 之间的区别?暂时性死区如何理解?
- Class、extends 是什么,有什么作用?
- 什么是 JS 闭包
- 说一下类的创建和继承,列举一下你所知道的继承方式
- 如何解决异步回调地狱
- 说一下图片的懒加载和预加载
- mouseover 和 mouseenter 的区别
- new 操作符做了哪些事情
- 改变函数内部 this 指针的指向函数(bind,apply,call 的区别),内在分别是如何实现的?
- JS 的各种位置,比如 clientHeight, scrollHeight, offsetHeight ,以及 scrollTop, offsetTop, clientTop * 的区别?
- 异步加载 JS 的方法
- Ajax 解决浏览器缓存问题
- 节流和防抖
- eval 是做什么的
- 对象深拷贝的简单实现
- 实现 JS 中所有对象的深度克隆(包装对象,Date 对象,正则对象)
- 实现一个 once 函数,传入函数参数只执行一次
- 将原生的 ajax 封装成 promise
- JS 监听对象属性的改变
- 如何实现一个私有变量,用 get 可以访问,不能直接访问
- 怎么控制一次加载一张图片,加载完后再加载下一张
- 如何实现 sleep 的效果(es5 或者 es6)
- Function.proto(getPrototypeOf)是什么?
- 箭头函数中 this 指向
- 数组常用方法有哪些
- 数组去重有哪些方法?
- 如何去除字符串首尾空格
- 说说你所知道的 JS 语言特性?
- 如何判断一个数组?
- JS 的全排列
- 谈谈你所理解的跨域,为什么会有这个问题?如何解决?
- null == undefined 输出什么?null === undefined 呢?
- 什么是按需加载
- 简单介绍一下 symbol
- 介绍一下 promise,及其底层如何实现
- JS 原型链,原型链的顶端是什么?Object 的原型是什么?Object 的原型的原型是什么?
- promise+Generator+Async 的使用
- JS 中 string 的 startwith 和 indexof 两种方法的区别
- JS 字符串转数字的方法
- 平时是怎么调试 JS 的
- 怎么获得对象上的属性
- async 和 await 具体该怎么用?
- 知道哪些 ES6,ES7 的语法
- promise 和 await/async 的关系
- JS 加载过程阻塞,解决方法。
- JS 对象类型,基本对象类型以及引用对象类型的区别
- 轮播的实现原理?假如一个页面上有两个轮播,你会怎么实现?
- 解释一下 JS 的事件循
- Localstorage、sessionStorage、cookie 的区别
- 解释一下 HTML5 Drag API
- 解释一下 webworker
- {} 和 [] 的 valueOf 和 toString 的结果是什么?
- 三种事件模型是什么?
- 介绍一下 V8 隐藏类
- AMD 和 CMD 规范的区别?说一下 CommonJS、AMD 和 CMD?
- 谈谈 JS 的运行机制
Vue生态
- 说说你对 Vue 的理解,有何优缺点?
- Vue 和 React 有什么不同?
- 什么是虚拟 DOM?
- 描述下 vue 的生命周期有哪些?分别做了什么事情?
- watch 怎么深度监听对象变化
- 删除数组用 delete 和 Vue.delete 有什么区别?
- watch 和 computed 有什么区别?
- v-for 没有 key 会发生什么问题?
- 谈谈 Vue 双向绑定原理
- v-model 是什么?有什么用呢?
- 在 vue 项目中如何引入第三方库?有哪些具体操作方法?
- Vue3.0 里为什么要用 Proxy API 替代 defineProperty API?
- Vue3.0 编译做了哪些优化?
- Vue3.0 新特性 —— Composition API 与 React.js 中 Hooks 的异同点
- Vue3.0 是如何变得更快的?dom diff 算法有何优化?
- vue 要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?
- vue 在 created 和 mounted 这两个生命周期中请求数据有什么区别呢?
- 说说你对 Proxy 的理解。
- Vue3.0性能提升主要是体现在哪些方面?
- vue3有哪些新的组件?
- Vue2.0 和 Vue3.0 有什么区别?
- Composition Api 与 Options Api 有什么不同?
- 对Vue项目你做过哪些性能优化?
- Vue组件通信的方式有哪些?
- Vue常用的修饰符有哪些?
- Vue中的$nextTick有什么作用?底层如何实现?
- v-show和v-if有什么区别?
- 有用过keep-alive吗?它有什么作用?
- 如何实现一个虚拟DOM吗?
- 为什么data属性是一个函数而不是一个对象,具体原因是什么?
- Vue2的初始化过程你有过了解吗,做了哪些事情?
- Vue3初始化的一个大概流程?
- vue3响应式api如何编写?
- 在Vue项目中你是如何做的SSR渲染?
计算机网络
- 什么是 Ajax,Ajax 都有哪些优点和缺点?
- 请介绍一下 XMLHTTPrequest 对象及常用方法和属性
- Ajax 的实现流程是怎样的?
- Ajax 接收到的数据类型有哪些,数据如何处理?
- 封装好的 Ajax 里的常见参数及其代表的含义
- Ajax 注意事项及适用和不适用场景
- 常见的 HTTP 状态码以及代表的意义
- 301 302 303 状态码的区别?
- 什么是同源策略
- 为什么会有跨域的问题出现,如何解决跨域问题
- Get 和 Post 的区别以及使用场景
- 解释 jsonp 的原理
- HTTP 与 HTTPS 的区别
- 简述 web 前端 Cookie 机制,并结合该机制说明会话保持原理
- 你知道的 HTTP 请求方式有几种
- 谈谈你理解的 RESTFUL 规范
- 解释一下三次握手是什么,具体流程。变为二次握手会发生什么问题?
- TCP 和 UDP 分别是什么?
- WebSocket 的实现和应用。
- 一个图片 url 访问后直接下载怎样实现?
- 说一下 http2.0
- 补充 400 和 401、403 状态码
- fetch发送2次请求的原因
- 对 HTML 语义化标签的理解
- Cookie 和 session 的区别
- 强缓存 和 协商缓存 区别?什么时候用哪个 ?本质是?
- cache-control 的值有哪些
- 谈谈 304 状态码
- 什么是 CDN,以及如何优化?
- DNS是什么
- 什么是四层、七层网络模型?
网络安全
- 什么是 xss 攻击及如何防范
- 什么是 ddox 攻击及如何防范?
- 什么是 csrf 攻击及如何防范?
前端工程化
- 如何理解前端模块化、前端组件化,二者有何区别?
- 如何理解前后端分离?
- webpack
- 有自己配置过 webpack 吗?如果需求是多页面与单页面并行,需要如何配置?
- Webpack 的优点是什么?
- Webpack 的构建流程是什么?从读取配置到输出文件这个过程尽量说全
- 说一下 Webpack 的热更新原理
- 有哪些常见的 Loader?他们是解决什么问题的?
- Loader 和 Plugin 的不同?
- 如何利用 Webpack 来优化前端性能
- 是否写过 Loader 和 Plugin?描述一下编写 loader 或 plugin 的思路?
- 使用 Webpack 开发时,你用过哪些可以提高效率的插件?
- 什么是长缓存?在 Webpack 中如何做到长缓存优化?
- 如何提高 Webpack 的构建速度?
- 怎么实现 Webpack 的按需加载?什么是神奇注释?
- Babel 的原理是什么?
- 如何写一个 babel 插件?
- rebase 与 merge 的区别?
- git reset、git revert 和 git checkout 有什么区别 ?
- webpack 和 vite 区别(模块化与流的区别)
- webpack文件指纹策略:hash chunkhash contenthash
性能优化
- 做过哪些前端性能优化相关的事情?
- 要加载大量图片,你有哪些方法优化方案?
- 列表无限滚动,数据越来越多,页面卡顿,如何解决?
- for(let i=0;i<1000000;i++){console.log(i)} 如何优化?
- 谈谈你是如何判断网站的性能的?
- 解释一下,性能指标 FP FCP FMP,如何查看 。
- 谈谈浏览器的渲染过程,DOM 树和渲染树的区别。
- 一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么。
- 什么是SPA单页面应用,首屏加载你是如何优化的
移动 web 开发
- 知道 PWA 吗
- 移动布局方案
- Rem 布局及其优缺点
- 讲讲 viewport 和移动端布局
- 移动端适配 1px 的问题
- 移动端性能优化相关经验
- 移动端兼容性
- 小程序
- 2X 图 3X 图适配
- 图片在安卓上,有些设备模糊问题
- 固定定位布局键盘挡住输入框内容
- click 的 300ms 延迟问题和点击穿透问题
- 防止手机中页面放大和缩小
- px、em、rem、%、vw、vh、vm 这些单位的区别
- 移动端适配- dpr 浅析
- 移动端扩展点击区域
- 上下拉动滚动条时卡顿、慢
- 长时间按住页面出现闪退
- webkit mask 兼容处理
- transiton 闪屏
研发流程
- 技术设计
- 设计文档需要涵盖哪些部分?
- 代码规范
- 谈谈 eslint
- 谈谈 commit message 规范
- 研发协同(Git)
- git 的基本使用方法
- git 工作流程
- 需要合并别人代码进来
- 需要切换分支
- 我们如何使用 git 和开源的码云或 github 上面的远端仓库的项目进行工作呢
- git、github、gitlab 三者之间的联系以及区别
- github 和码云的区别
- 提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的
- 如果本次提交误操作,如何撤销
- git 修改提交的历史信息
- 如何删除 github 和 gitlab 上的文件夹
- 如何查看分支提交的历史记录?查看某个文件的历史记录呢
- git 跟 svn 有什么区别
- 我们在本地工程常会修改一些配置文件,这些文件不需要被提交,而我们又不想每次执行 git status 时都让这些文件显示出来,我们该如何操作?
- git fetch 和 git merge 和 git pull 的区别。
- 如何把本地仓库的内容推向一个空的远程仓库
- 测试
- 单元测试如何做?
- 如何解决联调依赖问题?
- 提测阶段bug 和 线上bug 解决过程有和区别?
- 发布上线
- 流水线如何搭建
- 对 Docker 理解
- pm2 与 docker 有何区别?
Nodejs
- 对 Node.js 有没有了解,它有什么特点,适合做什么业务
- Node 和 前端项目怎么解决跨域的
- Node 的优点是什么?缺点是什么
- commonJS 中的 require/exports 和 ES6 中import/export 的区别是什么
- 简述同步和异步的区别,如何避免回调地狱,Node 的异步问题是如何解决的
- dependencies 和 devDependencies 两者区别
- 描述一下从接到 url 开始,到逻辑处理,到DB查询,到返回结果,整个过程是怎么处理的?
- 谈谈你对 Koa 和 Express 的理解,二者的区别是?
- 谈谈对 egg 和 nest.js 的理解,二者的区别是?
URL Scheme(URL协议)
在移动应用程序中,URL Scheme是一种用于在应用程序之间进行通信的机制。它允许一个应用程序通过特定的URL来打开另一个应用程序,并在打开后执行一些特定的操作。
URL Scheme的结构
一个URL Scheme是一个以特定格式构建的URL。它通常由两部分组成:Scheme和Path。
- Scheme:Scheme是URL的开头部分,用于指定要打开的应用程序。它以字母开头,后面跟随着字母、数字和一些特殊字符,例如
myapp://
。 - Path:Path是Scheme之后的部分,用于指定在目标应用程序中要执行的具体操作。它可以是一个命令、参数或其他标识符,例如
open?item=123
。
URL Scheme的用途
URL Scheme可以用于多种用途,包括但不限于以下几个方面:
- 打开应用程序:通过URL Scheme,可以从一个应用程序打开另一个应用程序。例如,可以通过点击一个URL链接或在其他应用程序中点击一个按钮来打开目标应用程序。
- 传递参数:URL Scheme可以传递一些参数给目标应用程序,以便应用程序知道要执行的操作或显示的内容。例如,可以通过URL Scheme传递一个商品ID,以便在目标应用程序中显示该商品的详细信息。
- 执行特定操作:URL Scheme还可以用于执行一些特定的操作,例如发送电子邮件、拨打电话、分享内容等。通过在URL中指定特定的命令,目标应用程序可以根据命令执行相应的操作。
如何使用URL Scheme
要在应用程序中使用URL Scheme,通常需要完成以下几个步骤:
- 注册URL Scheme:目标应用程序需要在其配置文件或代码中注册自己的URL Scheme。这样,其他应用程序才能通过URL打开它。
- 构建URL:在发送URL请求时,需要构建一个合法的URL,包括Scheme和Path等必要的信息。
- 处理URL请求:目标应用程序需要处理接收到的URL请求,并根据URL中的信息执行相应的操作。
示例
以下是一个示例URL Scheme的URL:
1 | myapp://open?item=123 |
这个URL使用了名为myapp
的Scheme,并传递了一个名为item
的参数,值为123
。目标应用程序可以解析这个URL,执行打开操作,并显示ID为123
的商品详细信息。
git 添加 ssh key
创建 SSH Key
1 | ssh-keygen -t rsa -C "tangxiaomiemail@gmail.com" |
如果一切顺利的话,可以在用户主目录里找到 .ssh 目录,里面有 id_rsa
和 id_rsa.pub
两个文件,这两个就是 SSH Key 的秘钥对,id_rsa 是私钥,不能泄露出去,id_rsa.pub 是公钥,可以放心地告诉任何人.
全局配置
1 | git config --global user.name "tangxiaomi" |
非全局配置 删除 --global
1 | git config user.name "tangxiaomi" |
查看配置
1 | git config --global user.name |
取消全局配置
1 | git config --global --unset user.name |
git submodule
添加
1 | git submodule add -b [指定分支] [仓库地址] [路径] |
命令执行完成,会在当前工程根路径下生成一个名为 .gitmodules
的文件,其中记录了子模块的信息。
.gitmodules
1 | [submodule "themes/icarus"] |
更新
1 | git submodule update |
删除
submodule
的删除稍微麻烦点:首先,要在 .gitmodules
文件中删除相应配置信息。然后,执行 git rm –cached
命令将子模块所在的文件从 git
中删除。
下载的工程带有 submodule
1 | git submodule update --init --recursive |
查看 sumodule 状态
1 | git submodule foreach git status |
不能更新
1 | git submodule update --remote |
Vue3中的ref解构与响应式问题
介绍 📝
Vue 3是一种流行的JavaScript框架,它提供了一种声明式的方式来构建用户界面。在Vue 3中,我们可以使用ref
函数来创建响应式数据。然而,当我们尝试对ref
解构进行操作时,可能会遇到一些响应式问题。本文将探讨Vue 3中ref
解构的使用、为什么会丢失响应式以及如何解决相关的问题。
ref
解构的使用 🧩
在Vue 3中,我们可以使用ref
函数创建一个响应式的数据对象。下面是一个简单的例子:
1 | import { ref } from 'vue'; |
在上面的例子中,我们使用ref
函数创建了一个名为count
的响应式数据对象。通过访问count.value
属性,我们可以获取和修改数据的值。
然而,当我们尝试对ref
解构进行操作时,可能会遇到一些问题。
ref
解构的响应式问题 🚫
当我们对ref
解构进行操作时,Vue 3无法正确地跟踪和更新数据的变化。下面是一个例子:
1 | import { ref } from 'vue'; |
在上面的例子中,我们通过解构将count
的值赋给value
变量。然而,当我们修改count
的值时,value
并没有更新。
这是因为解构操作会将count.value
的值复制给value
,而不是创建一个引用。因此,value
不再是一个响应式的数据对象,它无法与count
保持同步。
为什么会丢失响应式? 🤔
当我们对ref
解构进行操作时,原因是解构操作会将响应式对象的引用丢失。Vue 3的响应式系统是基于Proxy实现的,它会拦截对响应式对象的访问和修改。然而,当我们对解构后的变量进行操作时,Vue 3无法捕获到这些操作,因此无法正确地跟踪和更新数据的变化。
解决方案 🛠️
要解决ref
解构的响应式问题,我们可以使用Vue 3提供的toRef
函数。toRef
函数可以将一个响应式对象的属性转换为一个单独的响应式引用。
下面是一个使用toRef
函数的示例:
1 | import { ref, toRef } from 'vue'; |
在上面的例子中,我们使用toRef
函数将count.value
转换为一个新的响应式引用value
。通过访问value.value
属性,我们可以获取和修改数据的值。
使用toRef
函数后,value
将与count
保持同步,可以正确地跟踪和更新数据的变化。
TypeScript泛型
什么是泛型?
泛型是一种在编程语言中用于创建可重用代码的工具。它允许我们在定义函数、类或接口时延迟指定具体类型,而是在使用时动态地传入类型参数。
泛型函数 📝
在TypeScript中,我们可以使用泛型来创建可接受不同类型参数的函数。下面是一个简单的例子:
1 | function identity<T>(arg: T): T { |
在上面的例子中,我们定义了一个identity函数,它接受一个参数arg并返回该参数。使用<T>
语法来指定泛型类型,并在函数体中使用该类型。
在调用函数时,我们可以明确指定泛型类型,也可以让TypeScript根据传入的参数自动推断出类型。
常见场景: 泛型函数常用于处理各种类型的输入,并返回相同类型的输出。例如,数组的map
和filter
方法就是使用泛型函数来实现的。
泛型类 🏢
除了函数,我们还可以创建泛型类。泛型类允许我们在类的定义中使用泛型类型。下面是一个示例:
1 | class Container<T> { |
在上面的例子中,我们定义了一个Container类,它接受一个泛型类型参数T,并在构造函数中接受一个参数value。通过泛型类型,我们可以在类中使用该类型,并在实例化时传入具体类型。
常见场景: 泛型类常用于创建可重用的数据结构,例如栈、队列等。通过使用泛型类,我们可以在编写通用的数据结构时,不限制特定的数据类型。
泛型约束 🚧
有时候,我们希望对泛型进行一些限制,以确保只能传入特定类型。这时可以使用泛型约束。下面是一个示例:
1 | interface Lengthwise { |
在上面的例子中,我们定义了一个Lengthwise接口,它包含一个length属性。然后我们定义了一个loggingIdentity函数,它接受一个泛型参数T,并使用extends关键字对泛型进行约束,要求T必须实现Lengthwise接口。这样我们就可以在函数体中访问arg的length属性。
常见场景: 泛型约束常用于对泛型类型进行更精确的类型限制,以确保传入的参数具有特定的属性或方法。
泛型与工具类型的结合 🛠️
TypeScript提供了一些内置的工具类型(Utility Types),可以与泛型一起使用,以进一步增强泛型的能力。
常见工具类型:
Partial<T>
:将类型T的所有属性设为可选。Readonly<T>
:将类型T的所有属性设为只读。Pick<T, K>
:从类型T中选择指定的属性K。Omit<T, K>
:从类型T中排除指定的属性K。Record<K, T>
:创建一个具有指定类型T的属性K的对象。Exclude<T, U>
:从类型T中排除可以赋值给类型U的类型。Extract<T, U>
:从类型T中提取可以赋值给类型U的类型。NonNullable<T>
:从类型T中排除null和undefined。
这些工具类型可以与泛型一起使用,以便更灵活地处理类型。
常见场景: 泛型与工具类型的结合常用于处理复杂的类型转换、属性选择和排除等操作。
HSTS 强制 https
HSTS (HTTP Strict Transport Security)
是一种安全策略,用于强制浏览器使用 HTTPS 进行安全连接,防止恶意攻击者使用中间人攻击 (Man-in-the-middle攻击) 窃取用户数据。
🛡️ HSTS 的工作原理
HSTS 通过在 HTTPS 响应头中添加 Strict-Transport-Security
参数来实现。当用户第一次访问一个网站时,服务器返回的响应头中包含了 Strict-Transport-Security
参数,浏览器会记住该网站的 HSTS 头,之后再次访问该网站时,浏览器就会自动强制使用 HTTPS 进行连接,而不再允许使用 HTTP 协议进行访问。
🔑 HSTS 的作用
使用 HSTS 可以提供以下的安全保障:
- 防止中间人攻击:通过强制使用 HTTPS,HSTS 可以防止攻击者在用户和服务器之间插入恶意的中间人攻击,在传输过程中窃取用户的敏感信息。
- 安全可靠:HSTS 可以确保通过 HTTPS 连接的安全性和效率,从而更好地保护用户的隐私和安全。
- 提高搜索引擎排名:使用 HTTPS 进行加密的网站可以获得更高的搜索引擎排名,并提高用户的信任度和转化率。
- 提高网站性能:使用 HTTPS 加密通信可以降低网络拥塞和提高网站的性能。
⚙️ 如何设置 HSTS
要在网站中启用 HSTS,您需要在 HTTPS 响应头中添加一个 HSTS headers。您可以在 Web 服务器或应用程序中实现此功能,以下是一些具体步骤:
Apache 服务器
在 Apache 中,您可以通过编辑您的网站的 .htaccess 文件或 Apache 配置文件来添加 HSTS headers。编辑您的 .htaccess 文件,添加以下内容:
1 | Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" |
或者您可以编辑上面配置文件中的 VirtualHost 来全局设置 HSTS headers ,在 VirtualHost 中添加以下配置:
1 | <VirtualHost *:80> |
这将把所有请求重定向到 HTTPS 并将 HSTS headers 添加到响应头中。
Nginx 服务器
在 Nginx 中,编辑 Nginx 配置文件中与您的网站相关的配置。使用 add_header
命令添加 HSTS headers:
1 | server { |
IIS 服务器
在 IIS 中,您可以通过编辑您的网站的 web.config 文件来添加 HSTS headers。编辑 web.config 文件,添加以下内容:
1 | <system.webServer> |
添加 HSTS headers 之后,访问您的网站时,浏览器将会自动强制使用 HTTPS 进行连接,并且有效期 max-age
将在访问期间被记住,直到过期或 HSTS headers 被删除。
在实现 HSTS 的时候,最好先使用小的 max-age
值进行测试,以确保一切正常工作,之后再设定长期的值。另外,请注意不要在生产环境之前添加 HSTS 的预加载指令 preload
。该指令会将网站加入到浏览器的 HSTS 预加载列表中,必须遵守极其严格的要求和审核才能添加,预加载一旦结束就无法回退。
🚨 HSTS 的注意事项
- HSTS 只能保证浏览器和网站之间的通信是安全的,但无法防止其他形式的攻击。
- 如果网站使用了 HSTS,在浏览器上访问该网站时,会自动强制使用 HTTPS,请确保网站已正确配置 SSL 证书,否则用户无法访问该网站。
- HSTS 不适用于不支持 HTTPS 加密通信的浏览器或旧版浏览器。
💡 总结
HSTS 是一种用于强制浏览器使用 HTTPS 进行安全连接的安全策略,它可以有效地保护用户的隐私和安全,并提高网站的搜索引擎排名和性能。使用 HSTS 需要注意一些细节问题,但只要正确地实现和配置,可以轻松地提供更可靠和安全的服务。