者:五月君
转发链接:https://mp.weixin.qq.com/s/8f1f3IkOwqK0u5AEuTemlg
应用程序或工作簿中的所有**Name** 对象的集合。
每一个 Name 对象都代表一个单元格区域的定义名称。 名称可以是内置名称, 例如 Database、Print_Area 和 Auto_Open (或 custom names)。
RefersTo 参数必须以 A1 样式表示法指定,包括必要时使用的美元符 ($)。 例如,如果在 Sheet1 上选定了单元格 A10,并且通过将 RefersTo 参数“=Sheet1!A1:B1”而定义了一个名称,那么该新名称实际上指向单元格区域 A10:B10(因为指定的是相对引用)。 若要指定绝对引用,请使用“=Sheet1!$A:$B”。
方法
Add方法:为单元格区域定义新名称。
Item 方法:从Names集合中返回单个**Name** 对象。
属性
Application 属性:在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Count 属性:返回一个 Long 值,它表示集合中对象的数量。
Creator 属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
Parent 属性:返回指定对象的父对象。 只读。
代表单元格区域的定义名。 名称可以是内置名称, 例如 Database、Print_Area 和 Auto_Open (或 custom names)。
方法
Delete 方法:删除对象
属性
Application 属性:在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Category 属性:返回或设置指定名称的类别中的宏语言。 名称必须引用自定义的函数或命令。 读/写 String。
CategoryLocal 属性:返回或设置指定名称的类别中的用户语言名称引用自定义的函数或命令。 读/写 String。
Comment 属性:返回或设置与名称相关联的批注。 读/写 String。
Creator 属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
Index 属性:返回一个 long 类型值,该值代表相似对象的集合中对象的索引号。
MacroType 属性:返回或设置名称所引用的对象。 读/写**XlXLMMacroType**。 xlXLMMacroType可以是下列xlXLMMacroType常量之一。 ||xlCommand。 名称是指用户定义的宏。 ||xlFunction。 名称是指用户定义的函数。 ||xlNotXLM。 名称不引用函数或宏。
Name 属性:返回或设置一个String值,它代表对象的名称。
NameLocal 属性:返回或设置中的语言的用户对象的名称。 读/写 String。
Parent 属性:返回指定对象的父对象。 只读。
RefersTo 属性:用宏语言以 A1 样式表示法返回或设置名称所引用的公式(以等号开头)。 读/写 String。
RefersToLocal 属性:返回或设置名称引用的公式。 公式中的用户语言和处于 A1 样式表示法,开头等号。 读/写 String。
RefersToR1C1 属性:返回或设置名称引用的公式。 公式中的宏,语言和处于 R1C1 样式表示法,开头等号。 读/写 String。
RefersToR1C1Local 属性:返回或设置名称引用的公式。 此公式中的用户语言和处于 R1C1 样式表示法,开头等号。 读/写 String。
RefersToRange 属性:返回一个由Name对象引用的**Range** 对象。 只读。
ShortcutKey 属性:返回或设置定义为自定义 Microsoft Excel 4.0 宏命令的名称的快捷键。 读/写 String。
ValidWorkbookParameter 属性:如果指定的Name对象是有效的工作簿参数,则返回True 。 只读 Boolean。
Value 属性:返回或设置一个String值,该值代表公式的规定名称去引用。
Visible 属性:返回或设置一个布尔值, 确定对象是否可见。 读/写。如果将某个名称的Visible属性设置为False, 则该名称将不会出现在 "定义名称" 对话框中。
WorkbookParameter 属性:返回或设置为工作簿参数指定的Name对象。 读/写
代表工作表区域的数据有效性规则。
方法
Add方法:向指定区域添加数据验证。
Delete 方法:删除对象。
Modify 方法:修改指定区域的数据有效性验证。
属性
AlertStyle 属性:返回有效性检验警告样式。 只读的**XlDVAlertStyle**。信息图标,警告图标,禁止图标
Application 属性:
在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Creator 属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
ErrorMessage 属性:返回或设置数据有效性检验错误消息。 读/写 String。
ErrorTitle 属性:返回或设置数据有效性错误对话框的标题。 读/写 String。
Formula1 属性:返回与条件格式或者数据有效性相关联的值或表达式。 可为常量值、字符串值、单元格引用或公式。 只读的字符串。
Formula2 属性:返回与条件格式或数据有效性验证第二部分相关联的值或表达式。 仅在数据验证条件格式**运算符** 属性为xlBetween或xlNotBetween时使用。 可为常量值、字符串值、单元格引用或公式。 只读 String 类型。
IgnoreBlank 属性:如果指定区域内的数据有效性检验允许空值,则该值为 True。 读/写 Boolean。
IMEMode 属性:返回或设置日文输入规则的说明。 可以是下表中列出的**XlIMEMode** 常量之一。 Long 类型,可读写。
InCellDropdown 属性:如果数据有效性显示含有有效取值的下拉列表,则该属性值为 True。 读/写 Boolean。
InputMessage 属性:返回或设置数据有效性检验输入信息。 读/写 String。
InputTitle 属性:返回或设置数据有效性输入对话框的标题。 读/写 String。 限制为32个字符。
Operator 属性:返回一个Long值, 它代表数据有效性的运算符。
Parent 属性:返回指定对象的父对象。 只读。
ShowError 属性:如果用户输入无效数据时显示数据有效性检查错误消息,则该属性值为 True。 读/写 Boolean。
ShowInput 属性:如果用户在数据有效性检查区域内选定了某一单元格时,显示数据有效性检查输入消息,则该属性值为 True。 读/写 Boolean。
Type 属性:返回一个Long值, 它包含一个**XlDVType** 常量, 该常量代表区域的数据类型验证。
Value 属性:返回一个布尔值, 该值指示是否满足所有验证条件 (即, 如果该范围包含有效数据)。
代表页面设置说明。PageSetup 对象包含作为特性的所有页面设置属性(左边距、下边距、纸张大小等)。
属性(常用)
AlignMarginsHeaderFooter 属性:返回True excel 以对齐的边距设置页面设置选项中的页眉和页脚。 读/写 Boolean。
BlackAndWhite 属性:如果为true以黑白方式打印文档中的元素。 读/写 Boolean。
BottomMargin 属性:返回或设置下边距的大小, 以磅为单位。 读/写 Double。
CenterFooter 属性:居中对齐PageSetup对象中的页脚信息。 读/写 String。
CenterFooterPicture 属性:返回一个代表页脚的中心部分的图片的**图形** 对象。 用于设置图片的属性。
CenterHeader 属性:居中对齐中的PageSetup对象的头信息。 读/写 String。
CenterHeaderPicture 属性:返回一个代表中心节标头的图片的**图形** 对象。 用于设置图片的属性。
CenterHorizontally 属性:如果在页面的水平居中位置打印指定工作表,则该属性值为 True。 Boolean 类型,可读写。
CenterVertically 属性:True如果在上的垂直居中位置打印工作表。 读/写 Boolean。
DifferentFirstPageHeaderFooter 属性 :True,如此 如果不同的页眉或页脚使用第一页上。 读/写 Boolean。
Draft 属性:如果为true将图形不打印工作表。 读/写 Boolean。
EvenPage 属性:返回或设置工作簿或节的偶数页上的文本对齐方式。
FirstPage 属性:返回或设置工作簿或节的第一页上的文本对齐方式。
FirstPageNumber 属性:返回或设置打印指定工作表时第一页的页号。 如果xlAutomatic, Microsoft Excel 将选择第一个页码。 默认值为 xlAutomatic。 Long 类型,可读写。
FitToPagesTall 属性:返回或设置打印工作表时,对工作表进行缩放使用的页高。 仅应用于工作表。 读/写 Variant。
FitToPagesWide 属性:返回或设置打印工作表时,对工作表进行缩放使用的页宽。 仅应用于工作表。 读/写 Variant。
FooterMargin 属性:返回或设置从页面底部的距离,页脚,以磅为单位。 读/写 Double。
HeaderMargin 属性:返回或设置从页面顶部的距离,页眉,以磅为单位。 读/写 Double。
LeftFooter 属性:返回或设置工作簿或节的左页脚上的文本对齐方式。
LeftFooterPicture 属性:返回一个代表左侧的页脚节的图片的**图形** 对象。 用于设置图片的属性。
LeftHeader 属性:返回或设置工作簿或节的左页眉上的文本对齐方式。
LeftHeaderPicture 属性:返回一个代表左侧标头的各个部分的图片的**图形** 对象。 用于设置图片的属性。
LeftMargin 属性:以磅为单位返回或设置左边距的大小。 读/写Doub
OddAndEvenPagesHeaderFooter 属性 :True 指定的 PageSetup 对象是否的奇数和偶数页不同的页眉和页脚。 读/写 Boolean。
Order属性:返回或设置一个**XlOrder** 值, 该值代表 Microsoft Excel 在打印大型工作表时对页面编号时使用的顺序。
Orientation属性:返回或设置一个**XlPageOrientation** 值, 它代表纵向或横向打印模式。
Pages属性:返回或设置pages集合中页面的计数或项目号。
PaperSize 属性:返回或设置纸张大小。 XlPaperSize 类型,可读写。
PrintArea 属性:使用采用宏语言的 A1 样式引用,以字符串形式返回或设置要打印的区域。 读/写 String。
PrintComments 属性:返回或设置批注随工作表打印的方式。 读/写**XlPrintLocation**。
PrintErrors 属性:设置或返回一个**XlPrintErrors** 常量, 该常量指定显示的打印错误的类型。 该功能允许用户在打印工作表时取消错误显示。 可读写。
PrintGridlines 属性:True如果在上打印单元格网格线。 仅适用于工作表。 读/写 Boolean。
PrintHeadings 属性:如果为true行和列标题的打印此页。 仅适用于工作表。 读/写 Boolean。
PrintNotes 属性:True如果单元格注释打印作为表的尾注。 仅适用于工作表。 读/写 Boolean。
PrintQuality 属性:返回或设置打印质量。 读/写 Variant。
PrintTitleColumns 属性:返回或设置包含要重复左侧的每一页中,在语言的宏的 A1 样式表示法字符串形式的单元格的列。 读/写 String。
PrintTitleRows 属性:返回或设置那些包含在每一页顶部重复出现的单元格的行,用宏语言字符串以 A1 样式表示法表示。 读/写 String。
RightFooter 属性:返回或设置页的右边缘和页脚的右边界之间的距离 (以磅为单位)。 读/写 String。
RightFooterPicture 属性:返回一个代表页脚的右部分的图片的**图形** 对象。 用于设置图片的属性。
PageSetup.RightHeader 属性:返回或设置页眉的右侧部分。 读/写 String。
RightHeaderPicture 属性:指定应在右侧的标头中显示的图形图像。 只读。
RightMargin 属性:返回或设置的右边距的大小,以磅为单位。 读/写 Double。
ScaleWithDocHeaderFooter 属性:返回或设置如果文档的大小更改时应与文档扩展的页眉和页脚。 读/写 Boolean。
TopMargin 属性:返回或设置上边距的大小,以磅为单位。 读/写 Double。
Zoom属性:返回或设置一个Variant值, 它代表 Microsoft Excel 用于缩放工作表时使用的百分比 (10% 到 400%)。
代表工作表或区域的超链接的集合。
方法
add方法:向指定的区域或形状添加超链接。
Delete 方法:删除对象。
属性
Application 属性:在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Count 属性:返回一个 Long 值,它表示集合中对象的数量。
Creator 属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
Item 属性:从集合中返回一个对象。
Parent 属性:返回指定对象的父对象。 只读。
代表一个超链接。
方法
AddToFavorites 方法:将工作簿或超链接的快捷方式添加到“收藏夹”文件夹。
CreateNewDocument 方法:新建一篇链接到指定超链接的文档。
Delete 方法:删除对象。
Follow方法:显示缓存文档 (如果已下载)。 否则,此方法将解析该超链接,下载目标文档,并在相应的应用程序中显示此文档。
属性
Address 属性:返回或设置一个String值,该值代表目标文档的地址。
Application 属性:在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Creator属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
EmailSubject 属性:返回或设置指定超链接的电子邮件主题行的文本字符串。 主题行追加到超链接的地址。 读/写 String。
Name 属性:返回一个String值,它代表对象的名称。
Parent 属性:返回指定对象的父对象。 只读。
Range 属性:返回一个**range** 对象, 该对象代表指定的超链接所附加到的区域。
ScreenTip属性:返回或设置指定超链接的屏幕提示文字。 读/写 String。
Shape 属性:返回一个**Shape** 对象,它代表附加到指定的超链接的形状。
SubAddress 属性:返回或设置与超链接相关联的文档中的位置。 读/写 String。
TextToDisplay 属性:返回或设置指定超链接显示的文本。 默认值是超链接的地址。 读/写 String。
Type属性:返回一个Long值, 它包含一个**MsoHyperlinkType** 常量, 该常量代表 HTML 框架的位置。
代表单个列的筛选。Filter对象是 Filters 集合中的成员。 Filters 集合包含自动筛选区域中的所有筛选。
属性
Application 属性:在不使用对象识别符的情况下使用时, 此属性返回代表 Microsoft Excel 应用程序的**Application** 对象。 如果与对象识别符一起使用,则此属性返回代表指定对象的创建者的 Application 对象(可以将此属性与 OLE 自动化对象一起使用以返回该对象的应用程序)。 只读。
Count属性:返回集合中对象的数目。 只读 Long。
Creator 属性:返回一个 32 位整数,该整数指示在其中创建了此对象的应用程序。 只读 Long。
Criteria1 属性:筛选区域中返回指定列的第一个筛选的值。 只读的Variant。
Criteria2 属性:筛选区域中返回指定列的第二个筛选的值。 只读的Variant。
On 属性:True如果位于指定的筛选器。 只读 Boolean。
Operator属性:返回一个**XlAutoFilterOperator** 值, 该值代表关联指定筛选器所应用的两个条件的运算符。
Parent 属性:返回指定对象的父对象。 只读。
Filter 对象的集合, 该集合代表自动筛选区域中的所有筛选器。
代表对指定工作表的自动筛选。
方法
ApplyFilter 方法:应用指定的自动筛选对象。
ShowAllData 方法:显示自动筛选对象返回的所有数据。
属性(常用)
FilterMode 属性:如果工作表处于自动筛选模式, 则返回True 。 只读 Boolean 类型。
Filters 属性:返回一个**Filters** 集合, 该集合代表自动筛选区域中的所有筛选器。 此为只读属性。
Range属性:返回一个**range** 对象, 该对象代表应用指定的自动筛选的区域。
Sort属性:获取一个或多个列, 并对AutoFilter集合的排序顺序进行排序。
相关代码说明和实例可查询VBA开发文档 以上内容是本人自学笔记总结,欢迎指正,有关Excel的问题,可私信联系,互相交流讨论,共同进步,谢谢。
浏览器同源策略限制请求
同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
限制以下行为
有三个标签是允许跨域加载资源:
script标签不受策略影响,可以动态生成script去请求数据,但是仅限Get请求
原生实现
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回调执行函数
function onBack(res) {
alert(JSON.stringify(res));
}
</script>
vue实现
this.$http.jsonp(
'http://www.domain2.com:8080/login',
{
params: {},
jsonp: 'onBack'
}
).then(res => { console.log(res); }
)
仅限主域相同,子域不同的跨域应用场景
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域
<!-- 父窗口:http://www.domain.com/a.html -->
<iframe id="iframe" src="http://child.domain.com/b.html">
</iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
<!-- 子窗口:http://child.domain.com/b.html -->
<script>
document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> '+ window.parent.user);
</script>
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现: A域:a.html -> B域:b.html -> A域:c.html,
a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
postMessage一般用于解决以下问题
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递
<!-- a页面:http://www.domain1.com/a.html -->
<iframe id="iframe"
src="http://www.domain2.com/b.html"
style="display:none;">
</iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'
};
// 向domain2传送跨域数据
iframe.contentWindow.postMessage
(JSON.stringify(data),
'http://www.domain2.com');
};
// 接受domain2返回数据
window.addEventListener
('message', function(e) {
alert('data from domain2 ---> ' + e.data);
},
false);
</script>
<!-- b页面:http://www.domain2.com/b.html -->
<script>
// 接收domain1的数据
window.addEventListener
('message', function(e) {
alert('data from domain1 ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 处理后再发回domain1
window.parent.postMessage(JSON.stringify(data),
'http://www.domain1.com');
}
}, false);
</script>
服务端设置Access-Control-Allow-Origin即可
若要带cookie请求:前后端都需要设置。
前端: : 检查前端设置是否带cookie:xhr.withCredentials = true;
通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。
简单请求:
使用下列方法之一:
Content-Type 的值仅限于下列三者之一:
不符合以上条件的请求就肯定是复杂请求了。 复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求, 该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。
OPTIONS预检请求
请求头:
响应头
如果这六个以外的响应头要是想让客户端读取到,就需要设置Access-Control-Expose-Headers这个为响应头名了,比如Access-Control-Expose-Headers: Token
nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / {
add_header
Access-Control-Allow-Origin *;
}
反向代理
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
#proxy服务器
server {
listen
81;
server_name www.domain1.com;
location / {
proxy_pass
http://www.domain2.com:8080;
#反向代理
proxy_cookie_domain
www.domain2.com www.domain1.com;
# 修改cookie里域名
index index.html index.htm;
# 用webpack-dev-server等中间件代理接口访问nignx时,
# 此时无浏览器参与,故没有同源限制,面的跨域配置可不启用
add_header Access-Control-Allow-Origin
http://www.domain1.com;
# 当前端只跨域不带cookie时,可为*
add_header Access-Control-Allow-Credentials true;
}
}
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
<div>user input:
<input type="text">
</div>
<script src="./socket.io.js"></script>
<script>var socket = io('
http://www.domain2.com:8080');
// 连接成功处理
socket.on('connect', function() {
// 监听服务端消息
socket.on('message', function(msg) {
console.log('data from server: ---> ' + msg);
});
// 监听服务端关闭
socket.on('disconnect', function() {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input')
[0].onblur = function() {
socket.send(this.value);
};
</script>
实现原理:参考代码
实现原理:
轮播图原理就是图片的移动。所有轮播图片横向排列,在一个窗口中显示一张图片,窗口外的图片隐藏,每一次一排图片就是移动一张图片的距离,切换到下一张图片,即可实现图片轮播。
图片的移动有两种方式:
图片的自动播放,使用间隔定时器 setInterval
通过定位的方式,改变left或top的值,形成轮播图的效果
1、自动轮播:
用setInterval(func,time);
被调用的函数不断地自加,也就是不断地往后循环,当图片到最后一张时,让其跳转到第一张。
先将所有图片,下方指示点的样式设置为一样的,再对当前索引对应的图片,设置特别的样式。
2. 鼠标移入,移出事件
注意:
1)如果你想要通过点击事件来改变图片的移动时,就必须让鼠标移动到上面时设置清除计时器;因为如果不设置的话,当你通过点击事件改变它时,它自身也会自己改变,会出现混乱。
2)当清除完后,鼠标移出后需要重新启动计时器,这时候不能再给它设置var jishi;因为如果再加上var 的话,相当于重新又定义了一个变量,会有好几个计时器同时进行,会越来越快。
3. 手动轮播 底下指示点的按钮控制
判断点击的是哪个点,然后将它的索引值赋值给index,再通过调用change功能,实现它的改变。
4. 左右按钮的控制
让它实现自增或自减,然后调用change功能来改变样式。 其实这里的知识点和自动轮播里的知识点差不多。(从最后一张图片跳转到第一张图片 ,从第一张跳转到最后一张。)
无论是自动轮播,还是点击控制,都要加入change功能以及index 来实现对样式的控制,从而实现轮播的效果。
优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能
原理:
一张图片就是一个<img>标签,浏览器是否发起请求图片是根据<img>的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给<img>的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。
实现思路:
页面布局位置基础知识
网页可见区域宽: document.body.clientWidth; 网页可见区域高: document.body.clientHeight; 网页可见区域宽: document.body.offsetWidth (包括边线的宽); 网页可见区域高: document.body.offsetHeight (包括边线的高);
网页正文全文宽: document.body.scrollWidth; 网页正文全文高: document.body.scrollHeight; 网页被卷去的高: document.body.scrollTop; 网页被卷去的左: document.body.scrollLeft;
网页正文部分上: window.screenTop; 网页正文部分左: window.screenLeft; 屏幕分辨率的高: window.screen.height; 屏幕分辨率的宽: window.screen.width; 屏幕可用工作区高度: window.screen.availHeight;
可以给img标签统一自定义属性data-src='default.png',当检测到图片出现在窗口之后再补充src属性,此时才会进行图片资源加载。
function lazyload() {
const imgs = document.getElementsByTagName('img');
const len = imgs.length;
// 视口的高度
const viewHeight = document.documentElement.clientHeight;
// 滚动条高度
const scrollHeight = document.documentElement.scrollTop || document.body.scrollTop;
for (let i = 0; i < len; i++) {
const offsetHeight = imgs[i].offsetTop;
if (offsetHeight < viewHeight + scrollHeight) {
const src = imgs[i].dataset.src;
imgs[i].src = src;
}
}
}
// 可以使用节流优化一下
window.addEventListener('scroll', lazyload);
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一
SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
SSO 一般都需要一个独立的认证中心(passport),子系统的登录均得通过passport,子系统本身将不参与登录操作
当一个系统成功登录以后,passport将会颁发一个令牌给各个子系统,子系统可以拿着令牌会获取各自的受保护资源,为了减少频繁认证,各个子系统在被passport授权以后,会建立一个局部会话,在一定时间内可以无需再次向passport发起认证
cookie的domain属性设置为当前域的父域,并且父域的cookie会被子域所共享。path属性默认为web应用的上下文路径
利用 Cookie 的这个特点,我们只需要将Cookie的domain属性设置为父域的域名(主域名),同时将 Cookie的path属性设置为根路径,将 Session ID(或 Token)保存到父域中。这样所有的子域应用就都可以访问到这个Cookie
不过这要求应用系统的域名需建立在一个共同的主域名之下,如tieba.baidu.com 和 map.baidu.com,它们都建立在 baidu.com这个主域名之下,那么它们就可以通过这种方式来实现单点登录
这里只介绍使用过的:CAS(Central Authentication Service) 官网流程图:
app1登录
app2登录时:
上传大文件时,以下几个变量会影响我们的用户体验
分片上传:
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(Part)来进行分片上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件
大致流程如下:
断点续传:
断点续传指的是在下载或上传时,将下载或上传任务人为的划分为几个部分
每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。用户可以节省时间,提高速度
一般实现方式有两种:
上传过程中将文件在服务器写为临时文件,等全部写完了(文件上传完),将此临时文件重命名为正式文件即可
如果中途上传中断过,下次上传的时候根据当前临时文件大小,作为在客户端读取文件的偏移量,从此位置继续读取文件数据块,上传到服务器从此偏移量继续写入文件即可
实现思路:
整体思路比较简单,拿到文件,保存文件唯一性标识,切割文件,分段上传,每次上传一段,根据唯一性标识判断文件上传进度,直到文件的全部片段上传完毕
基于 token 的认证机制,只有在第一次使用需要输入账号密码,后续使用将不在输入账号密码。 其实在登陆的时候不仅传入账号、密码,还传入了手机的设备信息
在服务端验证账号、密码正确后,服务端会做两件事。
将 token 返回给移动端,移动端将 token 存入在本地,往后移动端都通过 token 访问服务端 API ,当然除了 token 之外,还需要携带设备信息,因为 token 可能会被劫持。带上设备信息之后,就算 token 被劫持也没有关系,因为设备信息是唯一的。
总结:设备信息加token唯一确定用户,完成登录认证
总结:PC端设备信息==>服务端生成二维码==> PC端显示==>定时器轮询二维码状态
总结:手机扫码==>手机端token+二维码ID发送到服务端==>服务器关联token和二维码ID ==> 生成token返回移动端 ==> PC端二维码状态更新
总结:PC端获取生成的token==> 完成登录==>正常访问(基于此token)
为一个下载按钮添加click事件,点击时动态生成一个表单,利用表单提交的功能来实现文件的下载
/**
* 下载文件
* @param {String} path - 请求的地址
* @param {String} fileName - 文件名
*/
function downloadFile (downloadUrl, fileName) {
// 创建表单
const formObj = document.createElement('form');
formObj.action = downloadUrl;
formObj.method = 'get';
formObj.style.display = 'none';
// 创建input,主要是起传参作用
const formItem = document.createElement('input');
formItem.value = fileName; // 传参的值
formItem.name = 'fileName'; // 传参的字段名
// 插入到网页中
formObj.appendChild(formItem);
document.body.appendChild(formObj);
formObj.submit(); // 发送请求
document.body.removeChild(formObj); // 发送完清除掉
}
<a href="example.jpg" download>点击下载</a>
<a href="example.jpg" download="test">点击下载</a> // 指定文件名
// 检测浏览器是否支持download属性
const isSupport = 'download' in document.createElement('a');
本质上和a标签访问下载链接一样
window.open('downloadFile.zip');
location.href = 'downloadFile.zip';
调用api,将文件流转为Blob二进制对象,
注:IE10以下不支持。
思路: 发请求获取二进制数据,转化为Blob对象,利用URL.createObjectUrl生成url地址,赋值在a标签的href属性上,结合download进行下载。
/**
* 下载文件
* @param {String} path - 下载地址/下载请求地址。
* @param {String} name - 下载文件的名字/重命名(考虑到兼容性问题,最好加上后缀名)
*/
downloadFile (path, name) {
const xhr = new XMLHttpRequest();
xhr.open('get', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function () {
if (this.status === 200 || this.status === 304) {
// 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob
if ('msSaveOrOpenBlob' in navigator) {
navigator.msSaveOrOpenBlob(this.response, name);
return;
}
/*
如果发送请求时不设置xhr.responseType = 'blob',
默认ajax请求会返回DOMString类型的数据,即字符串。
此时需要使用两处注释的代码,对返回的文本转化为Blob对象,然后创建blob url,
此时需要注释掉原本的const url = URL.createObjectURL(target.response)。
*/
/*
const blob = new Blob([this.response], { type: xhr.getResponseHeader('Content-Type') });
const url = URL.createObjectURL(blob);
*/
const url = URL.createObjectURL(this.response); // 使用上面则注释此行
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
};
}
// 上面方法本地测试有时会有跨域问题,下面使用axios重写一下
// 已经配置好proxy
downloadFile (path, name) {
axios.get({
url: path,
method: 'get'
}).then(res => {
const blob = new Blob([res.data], { type: res.headers['content-type'] });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
})
}
该方法不能缺少a标签的download属性的设置。
因为发请求时已设置返回数据类型为Blob类型(xhr.responseType = 'blob'),所以target.response就是一个Blob对象,打印出来会看到两个属性size和type。虽然type属性已指定了文件的类型,但是为了稳妥起见,还是在download属性值里指定后缀名,如Firefox不指定下载下来的文件就会不识别类型。
用法跟上面用Blob大同小异,基本上思路一样
不同点: 上面是利用Blob对象生成Blob URL, 这里则是生成Data URL,即base64编码后的url形式。
/**
* 下载文件
* @param {String} path - 下载地址/下载请求地址。
* @param {String} name - 下载文件的名字(考虑到兼容性问题,最好加上后缀名)
*/
downloadFile (path, name) {
const xhr = new XMLHttpRequest();
xhr.open('get', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function () {
if (this.status === 200 || this.status === 304) {
const fileReader = new FileReader();
fileReader.readAsDataURL(this.response);
fileReader.onload = function () {
const a = document.createElement('a');
a.style.display = 'none';
a.href = this.result;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
}
};
}
返回文件流的时候,在浏览器上观察接口返回的信息,会看到有这么一个header:Content-Disposition
其中包含了文件名:filename=和filename*=可以截取这段字符串中的这两个字段值了
// xhr是XMLHttpRequest对象
const content = xhr.getResponseHeader('content-disposition'); // 注意是全小写,自定义的header也是全小写
if (content) {
let name1 = content.match(/filename=(.*);/)[1]; // 获取filename的值
let name2 = content.match(/filename*=(.*)/)[1]; // 获取filename*的值
name1 = decodeURIComponent(name1);
name2 = decodeURIComponent(name2.substring(6)); // 这个下标6就是UTF-8''
}
监听页面滚动事件,分析clientHeight、scrollTop、scrollHeight三者的属性关系。
window.addEventListener('scroll', function() {
const clientHeight = document.documentElement.clientHeight;
const scrollTop = document.documentElement.scrollTop;
const scrollHeight = document.documentElement.scrollHeight;
if (clientHeight + scrollTop >= scrollHeight) {
// 检测到滚动至页面底部,进行后续操作
// ...
}
}, false);
渲染大数据时,合理使用createDocumentFragment和requestAnimationFrame,将操作切分为一小段一小段执行。
setTimeout(() => {
// 插入十万条数据
const total = 100000;
// 一次插入的数据
const once = 20;
// 插入数据需要的次数
const loopCount = Math.ceil(total / once);
let countOfRender = 0;
const ul = document.querySelector('ul');
// 添加数据的方法
function add() {
const fragment = document.createDocumentFragment();
for(let i = 0; i < once; i++) {
const li = document.createElement('li');
li.innerText = Math.floor(Math.random() * total);
fragment.appendChild(li);
}
ul.appendChild(fragment);
countOfRender += 1;
loop();
}
function loop() {
if(countOfRender < loopCount) {
window.requestAnimationFrame(add);
}
}
loop();
}, 0)
*请认真填写需求信息,我们会在24小时内与您取得联系。