首页

nginx配置rewrite的用法详解

seo达人

文章目录

rewrite在if中的用法

rewrite中break和last的用法

1.break和last在location{}外部时

2.break和last在location{}内部时

3.break和last用法总结

return的用法

rewrite的语法规则

rewrite应用实例

1.域名跳转(域名重定向)

2.http跳转https

3.跳转二级目录

4.动静态请求分离

5.防盗链配置

6.伪静态(将静态页面重写为动态)

7.多个if并用

rewrite在if中的用法

格式:if (条件判断) { 具体的rewrite规则 }



if条件判断语句由Nginx内置变量、逻辑判断符号和目标字符串三部分组成。

其中,内置变量是Nginx固定的非自定义的变量,如,$request_method, $request_uri等。

逻辑判断符号,有=, !=, ~, ~, !~, !~

!表示相反的意思,~为匹配符号,它右侧为正则表达式,区分大小写,而~为不区分大小写匹配。

目标字符串可以是正则表达式,通常不用加引号,但表达式中有特殊符号时,比如空格、花括号、分号等,需要用单引号引起来。

1

2

3

4

5

示例1:当http请求方法为post时,返回403状态码



if ($request_method = POST)

{

    return 403; 

}

1

2

3

4

示例2:通过浏览器标识匹配关键字,禁止IE浏览器访问



if ($http_user_agent ~
MSIE) 

{

    return 403;

}

1

2

3

4

限制多个浏览器:



if ($http_user_agent ~ "MSIE|firefox|Chrome")

{

    return 403;

}

1

2

3

4

示例3:当请求的文件不存在时,进行重定向或return状态码等处理操作



if(!-f $request_filename)

{

    rewrite 语句;

}

1

2

3

4

示例4:判断uri中某个参数的内容



if($request_uri ~
'gid=\d{6,8}/') 

{

    rewrite 语句;

}

1

2

3

4

\d表示数字,{6,8}表示数字出现的次数是6到8次,当uri中gid参数的值包含6-8个数字那么执行rewrite语句



rewrite中break和last的用法

两个指令用法相同,但含义不同,需要放到rewrite规则的末尾,用来控制重写后的链接是否继续被nginx配置执行(主要是rewrite、return指令)。



1.break和last在location{}外部时

测试示例:



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;



    rewrite /1.html /2.html;

    rewrite /2.html /3.html;

}

1

2

3

4

5

6

7

8

请求1.html文件时,会被重定向到2.html,然后被重定向到3.html,最后返回的文件为3.html



示例1:在rewrite 指令后面添加break



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;



    rewrite /1.html /2.html break;

    rewrite /2.html /3.html;

}

1

2

3

4

5

6

7

8

请求1.html文件时,会被重定向到2.html,然后直接返回2.html,break在此处的作用就是当匹配第一个rewrite指令成功时,不执行后面的rewrite指令



示例2:当break后面还有location{}的情况



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;



    rewrite /1.html /2.html break;

    rewrite /2.html /3.html;

    location /2.html {

        return 403;

    }

}

1

2

3

4

5

6

7

8

9

10

11

请求1.html文件时,会返回403状态码,当1.html被重定向到2.html时,break不会匹配后面的rewrite规则,但条件2.html匹配location{}定义的文件2.html,所以会执行return 403


以上两个示例中,将break换成last效果一样



2.break和last在location{}内部时

测试示例:



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;

    

    location / {

        rewrite /1.html /2.html;

        rewrite /2.html /3.html;

    }

    location /2.html

    {

        rewrite /2.html /a.html;

    }

    location /3.html

    {

        rewrite /3.html /b.html;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

请求1.html,会经过两次重定向到3.html,3.html又刚好匹配location /3.html{},所以返回b.html,当请求2.html时,会直接返回a.html,因为location /2.html {} 更精准,优先匹配



示例1:在rewrite后面添加break



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;

    

    location / {

        rewrite /1.html /2.html break;

        rewrite /2.html /3.html;

    }

    location /2.html

    {

        rewrite /2.html /a.html;

    }

    location /3.html

    {

        rewrite /3.html /b.html;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

请求1.html,会返回2.html,不会返回a.html,当break再location {} 内部时,遇到break后,当前location{} 以及后面的location{} 的指令都不再执行



示例2:在rewrite后面添加last



server{

    listen 80; 

    server_name test.com;

    root /data/wwwroot/test.com;

    

    location / {

        rewrite /1.html /2.html last;

        rewrite /2.html /3.html;

    }

    location /2.html

    {

        rewrite /2.html /a.html;

    }

    location /3.html

    {

        rewrite /3.html /b.html;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

请求1.html时,会返回a.html,在location {} 内部遇到last,当前location {}中剩下的指令不会再执行,但被重定向的url会重新匹配一遍location {}



3.break和last用法总结

1.当rewrite规则在location{}外,break和last作用一样,遇到break或last后,其后续的rewrite/return语句不再执行。但后续有location{}的话,还会近一步执行location{}里面的语句,前提是请求能匹配该location

2.当rewrite规则在location{}里,遇到break后,本location{}与其他location{}的所有rewrite/return规则都不再执行

3.当rewrite规则在location{}里,遇到last后,本location{}里后续rewrite/return规则不执行,但重写后的url再次从头匹配所有location



return的用法

该指令一般用于对请求的客户端直接返回响应状态码。在该作用域内return后面的所有nginx配置都是无效的,可以使用在server、location以及if配置中,除了支持跟状态码,还可以跟字符串或者url链接。



示例1:直接返回状态码



server{

    listen 80;

    server_name www.test.com;

    return 403;

    rewrite www.test.net;  

}

1

2

3

4

5

6

访问时,直接返回403状态码,return返回内容后,后面的配置rewrite不会执行



示例2:当return在if 判断中时



server {

.....



if ($request_uri ~ ".password|.bak")

{

    return 404;

    rewrite /(.*) /index.html;  

}

.....

}

1

2

3

4

5

6

7

8

9

10

请求的文件包含.password或.bak时,直接返回404,rewrite不会执行,但if {}外的配置会继续执行,return只在当前作用域中生效



示例3:返回字符串



server{

    listen 80;

    server_name www.test.com;

    return 200 "hello";

}

1

2

3

4

5

返回字符串必须加上状态码,否则会报错



示例4:返回nginx变量



location /1.html {

    return 200 "$host $request_uri";

}

1

2

3

示例5:返回url



server{

    listen 80;

    server_name www.test.com;

    return http://www.test.com/index2.html;

}

1

2

3

4

5

返回url时,必须以http://或https://开头



示例6:返回html代码



if ($http_referer ~ 'baidu.com') 

{

    return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";

}

1

2

3

4

当网站被黑了的时候,从百度点进网站是链接都会跳转到其他网站,可以使用该方法暂时处理

注意:return http://$host$request_uri; 在浏览器中会提示"重定向的次数过多"



rewrite的语法规则

格式:rewrite regex replacement [flag]



rewrite 配置可以在server、location以及if配置段内生效



regex 是用于匹配URI的正则表达式,其不会匹配到$host(域名)



replacement 是目标跳转的URI,可以以http://或者https://开头,也可以省略掉$host,直接写$request_uri部分



flag 用来设置rewrite对URI的处理行为,其中有break、last、rediect、permanent,其中break和last在前面已经介绍过,rediect和permanent的区别在于,前者为临时重定向(302),而后者是永久重定向(301),对于用户通过浏览器访问,这两者的效果是一致的。

但是,对于搜索引擎爬虫来说就有区别了,使用301更有利于SEO。所以,建议replacemnet是以http://或者https://开头的,flag使用permanent。



示例1:域名跳转



location / {

    rewrite /(.*) http://www.test.com/$1 permanent;

}

1

2

3

.*为正则表达式,表示uri,用()括起来,在后面的uri中可以调用它,第一次出现的()用$1调用,第二次出现的()用$2调用,以此类推。



示例2:域名跳转的第二种写法



location / {

    rewrite /. http://www.test.com$request_uri permanent;

}

1

2

3

示例3:文件跳转



server{

    listen 80;

    server_name www.test.com;

    root /data/wwwroot/test.com;

    index index.html;

    if ($request_uri !~ '^/web/')

    {

        rewrite /(.
) /web/$1 redirect;

    }

}

1

2

3

4

5

6

7

8

9

10

将uri请求的文件重定向到web/目录中去寻找



错误写法1:



server{

    listen 80;

    server_name www.test.com;

    root /data/wwwroot/test.com;

    index index.html;

    rewrite /(.*) /web/$1 redirect;

}

1

2

3

4

5

6

7

这样写会反复循环,直到浏览器最大循环限制次数,哪怕uri包含web/目录了,也会继续重定向/web/web/$1



错误写法2:



server{

    listen 80;

    server_name www.test.com;

    root /data/wwwroot/test.com;

    index index.html;

    rewrite /(.*) /web/$1 break;

}

1

2

3

4

5

6

7

添加break后不会导致循环,但如果uri中包含web/目录的情况下也会被重定向一次,重定向后的uri就是web/web/$1



rewrite应用实例

1.域名跳转(域名重定向)

单个域名的情况:



server{

    listen 80;

    server_name www.test.com;

    rewrite /(.) http://www.test.net/$1 permanent;    

}

1

2

3

4

5

多个域名的情况:



server{

    listen 80;

    server_name www.test.com www.test.net;

    if ($host != 'www.test.net')

    {

        rewrite /(.
) http://www.test.net/$1 permanent;

    }

}

1

2

3

4

5

6

7

8

2.http跳转https

server{

    listen 80;

    server_name www.test.com;

    rewrite /(.) https://www.test.com/$1 permanent;

}

1

2

3

4

5

3.跳转二级目录

server{

    listen 80;

    server_name bbs.test.com;

    rewrite /(.
) http://www.test.com/bbs/$1 last;

}

1

2

3

4

5

4.动静态请求分离

server{

    listen 80;

    server_name www.test.com;

    location ~ ..(jpg|jpeg|gif|css|png|js)$

    {

        rewrite /(.*) http://img.test.com/$1 permanent;

    }

}

1

2

3

4

5

6

7

8

假设www.test.com的服务器在国外,访问速度较慢,img.test.com的服务器在国内,访问速度正常,可以将访问www.test.com静态文件的请求重定向到img.test.com,提高文件返回速度



第二种写法:



server{

    listen 80;

    server_name www.test.com;

    if ( $uri ~ 'jpg|jpeg|gif|css|png|js$')

    {

        rewrite /(.
) http://img.test.com/$1 permanent;

    }

}

1

2

3

4

5

6

7

8

5.防盗链配置

server{

    listen 80;

    server_name www.test.com;

    location ~ ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$

    {

        valid_referers none blocked server_names
.test.com

        if ($invalid_referer)

        {

            return 403;

        }

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

配置防盗链避免别的网站引用www.test.com不想被引用的图片等文件



http_referer表示从哪儿点击进网站的,比如从百度搜索引擎访问的

valid_referers:白名单

invalid_referer:无效的(未在白名单中定义的)

none:允许referer为空(也就是允许直接访问,未从其他站点跳转的请求)

blocked:允许来源地址不含http/https



6.伪静态(将静态页面重写为动态)

location /  {

    rewrite ^([^.])/topic-(.+).html$ $1/portal.php?mod=topic&topic=$2 last;

    rewrite ^([^.]
)/forum-(\w+)-([0-9]+).html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;

    rewrite ^([^.])/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;

    rewrite ^([^.]
)/group-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=group&fid=$2&page=$3 last;

    rewrite ^([^.])/space-(username|uid)-(.+).html$ $1/home.php?mod=space&$2=$3 last;

    rewrite ^([^.]
)/(fid|tid)-([0-9]+).html$ $1/index.php?action=$2&value=$3 last;

}

1

2

3

4

5

6

7

8

示例为discuz的伪静态配置



7.多个if并用

location /{

    set $a 0;

    if ($document_uri !~ '^/abc')

    {

        set $a "${a}1"; #uri不以/abc开头时,$a的值变为01

    }

    if ($http_user_agent ~ 'ie6|firefox')

    {

       set $a "${a}2"; #浏览器标识包含ie6或者Firefox时,$a的值变为012

    }

    if ($a = "012") #当满足前两个if判断时,重写url

    {

        rewrite /(.
) /abc/$1 redirect;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

nginx配置文件语法不支持if嵌套,需要通过多个if并用判断时,使用标识变量值的方式处理



蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

使用docbox定制API文档

seo达人

使用docbox定制API文档

什么是docbox

docbox的安装

克隆项目

部署方式

docbox的编写

定制logo及UI

更换代码背景色

插入自己的logo

三列改为双列

其他定制UI



在公司实习了一个月,由于业务需要,我花了大概一周时间对docbox的安装,编写,定制化等进行了详细的研究,下面给大家分享一下我的总结

什么是docbox

Docbox是一个开源的REST API文档系统。它采用结构化的Markdown文件,并生成带有导航,固定链接的两列布局。下面是官方example图片:









docbox的安装

克隆项目

直接去官网https://github.com/tmcw/docbox,然后克隆即可。



部署方式

在使用npm命令前需要下载Node.js,npm会根据package.json配置文件中的依赖配置下载安装



接着,在/content下放入.md文件,并使用 npm run build 命令,生成一个包含所需要的js代码的bundle.js文件,同时创建一个新的index.html文件



重要的就是index.html、bundle.js、/css这三个文件和文件夹



docbox的编写

在/content下放入.md文件(markdown语法俺就不说了哈……)

对/src/custom/content.js中添加需要引入的.md文件位置和以及标题





注意: /src/custom/content.js中放入的是一级标题、二级和三级标题需要在.md文件中编写。





定制logo及UI

修改/src/custom/index.js文件

修改对应标签的属性即可,定制时修改生成的index.html是没有用的,因为index.html里的标签是被动态写死的。

更换代码背景色

<div class='round-left pad0y pad1x fill-green code small endpoint-method'>

1





<div class='endpoint dark fill-blue round '>

1





插入自己的logo





修改/src/components/app.js文件



三列改为双列

docbox默认情况下是显示三列布局,但我们可以在app.js下进行修改使之默认为双列布局。将下图的1改为2即可切换双列模式







其他定制UI

像下图一样,我们可以修改并填写代码得到自己想要的页面样式,比如说我在最上方加了一个固定位置的区域,然后可以在这个区域添加相应的超链接等。







app.js里可以找到图中对应的标签和js代码,docbox支持多种语言切换,我们在需要的地方加入我们想要加入的标签,并在/css文件夹中对相应的css文件添加样式就可以定制我们想要的UI啦!!!



下面给大家列出一些用docbox定制API文档的网站



Mapbox API文档

Mapillary的API文档和Tiles文档

HYCON 8th

Wall

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

一篇解决 thymeleaf 下拉选的选中问题

seo达人

说明:本文基于thymeleaf3.x



在做后台系统时多多少少都会遇到下拉选回显的问题,本次就总结一下如何利用thymeleaf简单快速的进行下拉选的回显。



两种情况:

1、下拉选的数据固定死了的情况下?

利用 th:field="${要选中的option的value值}" 属性,如下

<select id="bookKind" name="bookKind" th:field="${book.bookKind}" class="form-control">

        <option value="">请选择书的种类</option>

        <option value="1">编程语言</option>

        <option value="2">数据库</option>

        <option value="3">操作系统</option>

        <option value="4">办公软件</option>

        <option value="5">图形处理与多媒体</option>

</select>

         book是请求域中的实体类,当${book.bookKind}的值和 option 的 value值匹配上后,该option就会被选中。



        怎么样是不是很简单?如果是用ajax的话,还要先获取所有的option,循环遍历,判断value值是否相等,设置selected属性值为true,跳出循环,这一系列操作,thymeleaf一个属性值就搞定,所以孰轻孰重您就看着来吧!哈哈!



2、下拉选的数据没固定死时?

两个属性  th:each="bookKind : ${bookKinds}" th:selected="{bookKind} == ${book.bookKind}" 搞定,如下所示



<select id="bookKind" name="bookKind" class="form-control">

    <option th:each="bookKind : ${bookKinds}" th:selected="
{bookKind} == ${book.bookKind}" 

            th:value="${bookKind}" th:text="${bookKind}"></option>

</select>

        解释一下,先th:each遍历,*{bookKind}代表遍历出来的元素,判断与点击的者一栏的bookKind值是否一样,如果一样th:selected的值就为true,然后th:value 设置option的value 值,th:text 设置option的文本值。



试想一下,如果是用ajax会怎么样?1、先后台获取数据后,循环append(html标签) 2、再获取到当前记录的这列属性值,再获取到 1 中循环设置的option,在比对value值,设置选中,break等。而且第一个ajax还要整成同步的,不然 2 中可能获取不到 1 中的option元素。



 



最后说明:如果恰巧能解决你的问题,那就动一动您的小手,点个赞或者评论一下,让我看到你们,您的点赞或评论将会持续带给我不懈的动力!!!come on baby!Let's go!

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

vue-router编程式的导航

seo达人

什么是编程式的导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。



router.push(location, onComplete?, onAbort?)

注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。



想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。



HTML代码



<p @click="$router.push('/test/emitView')">跳转1</p>

<p @click="$router.push({path: '/test/propsView'})">path: '/test/propsView'</p>

<p @click="test">带参数的跳转</p>

<p @click="test1">提供了path,params会被忽略</p>

<p @click="$router.push({path: /test/propsView/${userId}})">

    url变为/test/propsView/123

</p>

<p @click="$router.push({path: '/test/propsView', query: {plan: 'private'}})">

    带参数的url变为/test/propsView?plan=private

</p>

Script中代码



test () {

    this.$router.push({

        name: 'routerView',

        params: {userId: this.userId, test: 333},

    })

    console.log(this.$route)

    console.log(this.$route.params)

},

test1 () {

    this.$router.push({ // 如果提供了 path,params 会被忽略

        path: 'routerView',

        params: {userId: this.userId, test: 333},

    })

    console.log(this.$route)

    console.log(this.$route.params)

},

router.replace(location, onComplete?, onAbort?)

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。



router.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()

router.go(1)

 

// 后退一步记录,等同于 history.back()

router.go(-1)

 

// 如果 history 记录不够用,则无反应

router.go(-100)

router.go(100)

router.back()

在浏览器记录中后退一步



router.forward()

在浏览器记录中前进一步


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

H5之外部浏览器唤起微信分享

seo达人

最近在做一个手机站,要求点击分享可以直接打开微信分享出去。而不是jiathis,share分享这种的点击出来二维码。在网上看了很多,都说APP能唤起微信,手机网页实现不了。也找了很多都不能直接唤起微信。

总结出来一个可以直接唤起微信的。适应手机qq浏览器和uc浏览器。

下面上代码,把这些直接放到要转发的页面里就可以了:

html部分:


        
  1. <script src="mshare.js"></script>//引进mshare.js
  2. <button data-mshare="0">点击弹出原生分享面板</button>
  3. <button data-mshare="1">点击触发朋友圈分享</button>
  4. <button data-mshare="2">点击触发发送给微信朋友</button>

js部分:


        
  1. <script>
  2. var mshare = new mShare({
  3. title: 'Lorem ipsum dolor sit.',
  4. url: 'http://m.ly.com',
  5. desc: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat inventore minima voluptates.',
  6. img: 'http://placehold.it/150x150'
  7. });
  8. $('button').click(function () {
  9. // 1 ==> 朋友圈 2 ==> 朋友 0 ==> 直接弹出原生
  10. mshare.init(+$(this).data('mshare'));
  11. });
  12. </script>

下面是mshare.js的代码分享,把这些代码新建一个js文件放进去,然后在页面中引进就ok了。


        
  1. /**
  2. * 此插件主要作用是在UC和QQ两个主流浏览器
  3. * 上面触发微信分享到朋友圈或发送给朋友的功能
  4. */
  5. 'use strict';
  6. var UA = navigator.appVersion;
  7. /**
  8. * 是否是 UC 浏览器
  9. */
  10. var uc = UA.split('UCBrowser/').length > 1 ? 1 : 0;
  11. /**
  12. * 判断 qq 浏览器
  13. * 然而qq浏览器分高低版本
  14. * 2 代表高版本
  15. * 1 代表低版本
  16. */
  17. var qq = UA.split('MQQBrowser/').length > 1 ? 2 : 0;
  18. /**
  19. * 是否是微信
  20. */
  21. var wx = /micromessenger/i.test(UA);
  22. /**
  23. * 浏览器版本
  24. */
  25. var qqVs = qq ? parseFloat(UA.split('MQQBrowser/')[1]) : 0;
  26. var ucVs = uc ? parseFloat(UA.split('UCBrowser/')[1]) : 0;
  27. /**
  28. * 获取操作系统信息 iPhone(1) Android(2)
  29. */
  30. var os = (function () {
  31. var ua = navigator.userAgent;
  32. if (/iphone|ipod/i.test(ua)) {
  33. return 1;
  34. } else if (/android/i.test(ua)) {
  35. return 2;
  36. } else {
  37. return 0;
  38. }
  39. }());
  40. /**
  41. * qq浏览器下面 是否加载好了相应的api文件
  42. */
  43. var qqBridgeLoaded = false;
  44. // 进一步细化版本和平台判断
  45. if ((qq && qqVs < 5.4 && os == 1) || (qq && qqVs < 5.3 && os == 1)) {
  46. qq = 0;
  47. } else {
  48. if (qq && qqVs < 5.4 && os == 2) {
  49. qq = 1;
  50. } else {
  51. if (uc && ((ucVs < 10.2 && os == 1) || (ucVs < 9.7 && os == 2))) {
  52. uc = 0;
  53. }
  54. }
  55. }
  56. /**
  57. * qq浏览器下面 根据不同版本 加载对应的bridge
  58. * @method loadqqApi
  59. * @param {Function} cb 回调函数
  60. */
  61. function loadqqApi(cb) {
  62. // qq == 0
  63. if (!qq) {
  64. return cb && cb();
  65. }
  66. var script = document.createElement('script');
  67. script.src = (+qq === 1) ? '//3gimg.qq.com/html5/js/qb.js' : '//jsapi.qq.com/get?api=app.share';
  68. /**
  69. * 需要等加载过 qq 的 bridge 脚本之后
  70. * 再去初始化分享组件
  71. */
  72. script.onload = function () {
  73. cb && cb();
  74. };
  75. document.body.appendChild(script);
  76. }
  77. /**
  78. * UC浏览器分享
  79. * @method ucShare
  80. */
  81. function ucShare(config) {
  82. // ['title', 'content', 'url', 'platform', 'disablePlatform', 'source', 'htmlID']
  83. // 关于platform
  84. // ios: kWeixin || kWeixinFriend;
  85. // android: WechatFriends || WechatTimeline
  86. // uc 分享会直接使用截图
  87. var platform = '';
  88. var shareInfo = null;
  89. // 指定了分享类型
  90. if (config.type) {
  91. if (os == 2) {
  92. platform = config.type == 1 ? 'WechatTimeline' : 'WechatFriends';
  93. } else if (os == 1) {
  94. platform = config.type == 1 ? 'kWeixinFriend' : 'kWeixin';
  95. }
  96. }
  97. shareInfo = [config.title, config.desc, config.url, platform, '', '', ''];
  98. // android
  99. if (window.ucweb) {
  100. ucweb.startRequest && ucweb.startRequest('shell.page_share', shareInfo);
  101. return;
  102. }
  103. if (window.ucbrowser) {
  104. ucbrowser.web_share && ucbrowser.web_share.apply(null, shareInfo);
  105. return;
  106. }
  107. }
  108. /**
  109. * qq 浏览器分享函数
  110. * @method qqShare
  111. */
  112. function qqShare(config) {
  113. var type = config.type;
  114. //微信好友 1, 微信朋友圈 8
  115. type = type ? ((type == 1) ? 8 : 1) : '';
  116. var share = function () {
  117. var shareInfo = {
  118. 'url': config.url,
  119. 'title': config.title,
  120. 'description': config.desc,
  121. 'img_url': config.img,
  122. 'img_title': config.title,
  123. 'to_app': type,
  124. 'cus_txt': ''
  125. };
  126. if (window.browser) {
  127. browser.app && browser.app.share(shareInfo);
  128. } else if (window.qb) {
  129. qb.share && qb.share(shareInfo);
  130. }
  131. };
  132. if (qqBridgeLoaded) {
  133. share();
  134. } else {
  135. loadqqApi(share);
  136. }
  137. }
  138. /**
  139. * 对外暴露的接口函数
  140. * @method mShare
  141. * @param {Object} config 配置对象
  142. */
  143. function mShare(config) {
  144. this.config = config;
  145. this.init = function (type) {
  146. if (typeof type != 'undefined') this.config.type = type;
  147. try {
  148. if (uc) {
  149. ucShare(this.config);
  150. } else if (qq && !wx) {
  151. qqShare(this.config);
  152. }
  153. } catch (e) {}
  154. }
  155. }
  156. // 预加载 qq bridge
  157. loadqqApi(function () {
  158. qqBridgeLoaded = true;
  159. });
  160. if (typeof module === 'object' && module.exports) {
  161. module.exports = mShare;
  162. } else {
  163. window.mShare = mShare;
  164. }

好了,这样就可以直接唤起微信进行分享啦

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

calc的使用

seo达人

       有张页面是要求要一屏展示,我想到了媒体查询,也想到了vw和vh。我先用vw和vh来布局,分为上,中,下三部分。每块计算宽高,vw和vh可以实现响应式布局,所以就用上了。但媒体查询用上了却发现在这边不好用,这时使用上了calc()属性。因为上一个人引入了video.js并加上id:#myVideo ,这边也做相应的计算处理。



注意:要有空格



calc()能计算的计算表达式里,在加号(“+”)和减号(“-”)两边要留空格,而乘号(“”)和除号(“”)没有这个要求。 



.video_rel {

        height: calc(100% - 66px);

        width: calc(51.3% - 60px);

 

        #myVideo {

            width: 100%;

            height: 100%;

        }

    }

CSS3引入了一个有用的功能,就是calc()函数。在指定元素高度或宽度时,你可以基于计算设定,而不是简单的使用固定数值。这种功能在自适应网页布局设计中格外有用——针对不同尺寸的设备,你需要动态的调整元素的大小,产生适合屏幕大小的不同布局。

 

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

六、HTTP协议中的缓存

seo达人

一、缓存简介

缓存无处不在,浏览器端的缓存、服务器端的缓存、代理服务器的缓存、对象缓存、数据库也有缓存……HTTP中具有缓存功能的是浏览器缓存和代理服务器缓存。下面说一下缓存的优点:



1.减少冗余的数据传输,节省了传输时间



2.减少服务器的负担,大大提高了网站的性能



3.加快了客户端加载网页的速度



二、使用Fiddler如何查看缓存的Header

与缓存相关的内容放在Header中的Cache项里;Requests和Responses均是这样。如图:







三、缓存的新鲜度(通过什么方式判断其是否,如何刷新缓存)

Web服务器通过两种方式判断浏览器缓存是否:



(1)浏览器把缓存文件的最后修改时间通过Header“If-Modified-Since”项传递给Web服务器。



(2)浏览器把缓存文件的ETag通过Header“If-None-Match”项传递给Web服务器。



简单描述一下,浏览器端想请求一个文档,它首先检查本地缓存,发现存在这个文档的缓存,获取缓存文档的最后修改时间,发送请求,将值放在Header中的“If-Modified-Since”项传递给Web服务器。Web服务器接收到请求后,将服务器的文档修改时间(Last-Modified)与HTTP请求中的header中的“If-Modified-Since”值相比较,有两种情况,如下面图示:



1.缓存有效:







2.缓存无效:







截图举例:







上面说的是If-Modified-Since值对比的方式;下面说一下ETa'g;



四、ETag

ETag(Entity Tag):实体标签;是根据实体内容生成的一段hash字符串(类似MD5之后的结果),可以用来标识资源的状态(当资源发送变化时,ETag也会跟着改变);ETag是Web服务端产生的,然后通过response响应给浏览器。使用ETag,主要解决Last-Modified无法解决的情况:



(1.某些服务器不能得到文件的If-Modified-Since来判断文件是否更新;



(2.某些文件修改非常频繁,以小于秒的单元进行修改,而Last-Modified最单元为秒;



(3.有些文件最后修改时间变化了,但是内容并没有变化,所以我们不希望浏览器以为文件已变化了;







五、与缓存相关的header

字段名称 释义

Cache-Control:max-age=0 以秒为单位

If-Modified-Since:Fri, 11 Jan 2019 01:55:04 GMT 缓存文件的最后修改时间

If-None-Match:W/"5c37f778-732" 缓存文件的Etag的值

Cache-Control:no-cache 不使用缓存

Pragma:no-cache 不使用缓存

Cache-Control:public 响应被缓存,可以共享与多用户

Cache-Control:private 响应只能私有缓存,不可共享

Cache-Control:no-store 绝对禁止缓存(机密、敏感文件)

Cache-Control:max-age=60 60秒后缓存过期(相对时间)

Date:Fri, 11 Jan 2019 01:55:04 GMT 当前发送时间

Expires:Fri, 11 Jan 2019 01:55:04 GMT 缓存过期时间设置(绝对时间)

Last-Modified:Fri, 11 Jan 2019 01:55:04 GMT 服务器端文件的最后修改时间

Etag:W/"5c37f778-732" 服务器端文件的Etag值

六、关于缓存的常识

1.如何让浏览器不使用缓存?



答:【Ctrl+F5】快捷键强制刷新浏览器,让浏览器不使用缓存;此时Fiddler抓包所看到的请求Header中都会带有Cache-Control:no-cache;







2.如何让浏览器直接使用缓存,不请求服务器进行缓存验证?



答:第一次访问与第二次访问同一个网页;(注意:第二次访问时,输入网址,直接回车)浏览器会直接使用有效的缓存,而不会发生HTTP请求去服务器验证缓存,这种情况称之为缓存命中;



使用Fiddler抓包,现象:第一次访问,有70多个Session;第二次访问,仅40多个请求;



3.浏览器均可在设置中设置不使用缓存;



4.公有缓存、私有缓存的区别:一个可以多个不同的客户端使用,一个只可唯一的客户端使用;


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

JS中钩子函数与回调函数的区别

seo达人

测试代码

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <title>Title</title>

</head>

<body>

    <button id="btn">按钮</button>

    <script>

        let btn = document.getElementById("btn");

        btn.onclick = () => { // 钩子函数

            console.log('我是钩子函数');

        }

 

        btn.addEventListener("click",() =>{ // 回调函数

            console.log('我是回调函数');

        });

        // 这是给btn绑定了一个监听器,后面那个函数是它的回调函数,

        // 因为消息捕获的过程我们并不能参与,而在捕获执行完毕的时候,

        // 回调函数才会执行,我们可以把对消息的处理写在回调函数里。

    </script>

</body>

</html>

点击按钮后代码输出如下:







回调函数和钩子函数的区别根本上是

钩子函数在捕获消息的第一时间就执行,而回调函数是捕获结束时,最后一个被执行的。



什么是钩子函数

一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。

钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子函数。 



什么是回调函数

回调函数其实是调用者将回调函数的指针传递给了调用函数,当调用函数执行完毕后,通过函数指针来调用回调函数。



钩子函数和回调函数都是事件处理函数


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

数组常用的方法

seo达人

数组常见方法

数组的方法

一、join() 方法 ----->不会改变原数组

二、concat() 方法 ----->不会改变原数组

三、splice(index, num, item) ----->会改变原数组

  1. splice(index, num) 删除功能
  2. splice(index, 0, ...item)
  3. splice(index, num, item)
  4. splice(index)

    四、slice() -----> 不会改变原数组

    五、push() 和 pop() ----->会改变原数组

    六、shift() 和 unshift() -----> 会改变原数组

    七、sort() -----> 会改变原数组

    八、reverse() ----->会改变原数组

    九、indexOf() 和 lastIndexOf()

    十、includes()

    十一、forEach()

    十二、map() -----> 不会改变原数组

    十三、filter() -----> 不会改变原数组

    十四、every()

    十五、some()

    十六、reduce() 和 reduceRight()

    十七、Array.from() 将类数组转化为数组

    十八、Array.of() 方法用于将一组值转化为数组

    十九、数组实例的 find() 和 findIndex()

    二十、扁平化数组 flat() 方法 -----> 不会改变原数组

    数组的方法

    一、join() 方法 ----->不会改变原数组

    该方法可以将数组里面的元素,通过指定的分隔符以字符串的形式连接起来

    返回值:返回新的字符串



    // join() 将数组转化为字符串

    let arr = [1, 2, 3, 4, 5]

    let str1 = arr.join('|')

    console.log(arr) // [1, 2, 3, 4, 5]

    console.log(str1) // 1|2|3|4|5

    // 当传空字符串时

    let str2 = arr.join('') // 12345

    // 当不传时

    let str3 = arr.join() // 1,2,3,4,5

    1

    2

    3

    4

    5

    6

    7

    8

    9

    二、concat() 方法 ----->不会改变原数组

    该方法可以把两个数组里的元素拼接成一个新的数组

    返回值:返回拼接后的新数组



    let arr1 = [0, 1, 2]

    let arr2 = [2, 3, 4]

    let arr = arr1.concat(arr2)

    // 传入二维数组

    let arrCopy = arr1.concat([12, [17, 26]])

    console.log(arrCopy) // [0, 1, 2, 12, [17, 26]]

    console.log(arr) // [0, 1, 2, 2, 3, 4]

    console.log(arr1) // [0, 1, 2]

    console.log(arr2) // [2, 3, 4]



    // ES6 扩展运算符

    let a = [1, 2]

    let b = [2, 3]

    let ab = [...a, ...b] // [1, 2, 2, 3]

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    三、splice(index, num, item) ----->会改变原数组

    index 参数:必传,整数,规定添加或者删除的位置,使用负数时,从数组尾部规定位置

    num 参数:必传,要删除的数量,如果为 0,则不删除项目

    item 参数:可选参数,可以是多个,想数组添加的新项目

    splice 具有删除,插入,替换的功能


  5. splice(index, num) 删除功能

    index 参数:开始位置的索引



    num 参数:要删除元素的个数



    返回值:返回的是包含被删除元素的数组对象



    // 删除功能

    let array = [1, 2, 3, 4, 5]

    let newArr = array.splice(2, 2)

    console.log(newArr) // [1, 2, 5]

    console.log(array) // [3, 4]



    1

    2

    3

    4

    5

    6
  6. splice(index, 0, …item)

    index 参数:插入元素的索引值

    0 参数:不删除

    // 插入功能

    let arr = ['a', 'b', 'c', 'd', 'e']

    let newArr = arr.splice(1, 0, ['插入', 1217])

    console.log(newArr) // []

    console.log(arr) // ['a', ['插入', 1217], 'b', 'c', 'd', 'e']



    1

    2

    3

    4

    5

    6
  7. splice(index, num, item)

    index 参数:开始的索引位置

    num 参数:删除的项个数

    item 参数:替换项

    返回值:返回包含被删除的元素的数组对象

    let arr = [1, 2, 3, 4, 5]

    let newArr = arr.splice(2, 2, '替换', '1226')

    console.log(newArr) // [3, 4]

    console.log(arr) // [1, 2, '替换', '1226', 5]



    1

    2

    3

    4

    5
  8. splice(index)

    当只传一个值时,表示从传入的 index 索引值开始截取到最后

    let arr = [1, 2, 3, 4, 5]

    let newArr = arr.splice(3)

    console.log(newArr) // [4, 5]

    console.log(arr) // [1, 2, 3]

    1

    2

    3

    4

    四、slice() -----> 不会改变原数组

    返回从原数组中指定开始下标到结束下标之间的项组成的新数组

    slice() 方法可以接受一或两个参数,即要返回项的起始位置和结束位置

    array.slice(2) 若只设置一个参数,起始位置为2(包含下标2)开始到数组最后

    array.slice(2, 5) 若设置两个参数,起始下标为2(包含下标2)到结束下标5(不包含下标5)的数组

    当 slice() 参数中有负数时,将负数加上数组的长度值来替换该位置的数

    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]

    let copyArr1 = arr.slice(2) // [3, 4, 5, 6, 7, 8, 9]

    let copyArr2 = arr.slice(2, 5) // [3, 4, 5] 

    let copyArr3 = arr.slice(-2) // [8, 9]

    let copyArr4 = arr.slice(2, -2) // [3, 4, 5, 6, 7]

    let copyArr5 = arr.slice(-2, -5) // []

    let copyArr6 = arr.slice(-5, -2) // [5, 6, 7]

    console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]



    1

    2

    3

    4

    5

    6

    7

    8

    9

    五、push() 和 pop() ----->会改变原数组

    push() 可以接受任意数量的参数,将其逐个添加到数组的末尾,并返回修改后数组的长度(改变了原数组)

    pop() 删掉数组末尾最后一项,改变了数组的 length 值,并返回删除的项

    let arr = [1, 2, 3, 4, 5]

    let count = arr.push(0, 1217)

    console.log(count) // 7

    console.loh(arr) // [1, 2, 3, 4, 5, 0, 1217]



    let item = arr.pop()

    console.log(item) // 1217

    console.log(arr) // [1, 2, 3, 4, 5, 0]

    1

    2

    3

    4

    5

    6

    7

    8

    六、shift() 和 unshift() -----> 会改变原数组

    shift() 删除原数组的第一项,并返回删除元素的值,如果数组为空折返回 undefined

    unshift() 将参数添加到原数组的开头,并返回数组的长度

    let arr = [1, 2, 3, 4, 5]

    let item = arr.shift()

    console.log(item) // 1

    console.log(arr) // [2, 3, 4, 5]



    let count = arr.unshift(0, 'Jack')

    console.log(count) // 6

    console.log(arr) // [0, 'Jack', 2, 3, 4, 5]

    1

    2

    3

    4

    5

    6

    7

    8

    七、sort() -----> 会改变原数组

    在排序时,sort() 方法会调用每个数组项的 toString() 转型方法,然后比较得到的字符串,已确定如何排序,其本质是比较字符串的 ASCII 编码

    即使数组中的每一项都是数值,sort() 方法比较的也是字符串,因此会出现以下情况:

    let arr1 = ['a', 'd', 'e', 'b', 'c']

    console.log(arr1.sort()) // ['a', 'b', 'c', 'd', 'e']



    let arr2 = [12, 26, 3, 99, 52]

    console.log(arr2.sort()) // [12, 26, 3, 52, 99]



    1

    2

    3

    4

    5

    6

    解决办法



    let arr3 = [12, 26, 3, 99, 52]

    arr3.sort((a, b) => {

    return a -b

    })

    console.log(arr3) // [3, 12, 26, 52, 99]

    1

    2

    3

    4

    5

    冒泡排序(优化版)



    function mySort (arr) {

    let count = 0 // 记录循环次数

    // 外层循环  控制循环的次数,每次找到最大值

    for (let i = 0; i < arr.length - 1; i++) {

    count++

    // 判断是否排序好了

    let isSort = true // 初始值默认已经排序好了

    for (let j = 0; j < arr.length - 1 - i; j++) {

    count++

    if (arr[j] > arr[j + 1]) {

    isSort = false

    // 交换位置

    let tmp = arr[j]

    arr[j] = arr[j + 1]

    arr[j + 1] = tmp

    }

    }

    // 某一趟结束,判断一下是否结束

    // 如何判断是否排序好,根据是否发生了位置交换,如果发生了位置交换就说明没有排序好

    if (isSort) {

    break

    }

    }

    console.log(count)

    return arr

    }

    mySort([12, 26, 17, 520, 99])



    // 打印结果:count 9

    // arr [12, 17, 26, 99, 520]



    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    八、reverse() ----->会改变原数组

    反转数组项的顺序

    let arr = [1, 2, 3, 4, 5]

    arr.reverse()

    console.log(arr) // [5, 4, 3, 2, 1]



    1

    2

    3

    4

    九、indexOf() 和 lastIndexOf()

    indexOf() 接受两个参数:要查找的项和查找起点位置的索引(可选项),其中从数组的开头开始向后查找

    lastIndexOf() 接受两个参数:要查找的项和查找起点位置的索引(可选项),其中是从数组的末尾开始向前查找

    返回值:当存在时,返回要查找的项在数组中首次出现的索引值;当不存在时,返回 -1

    可以用来判断一个值是否存在数组中



    let arr = [1, 2, 3, 5, 7, 7, 8, 5, 12, 17]

    console.log(arr.indexOf(5)) // 3

    console.log(arr.lastIndexOf(5)) // 7



    console.log(arr.indexOf(5, 2)) // 3

    console.log(arr.lastIndexOf(5, 4)) // 3



    console.log(arr.indexOf('5')) // -1

    1

    2

    3

    4

    5

    6

    7

    8

    十、includes()

    Array.prototype.includes() 数组实例的方法

    返回一个布尔值,表示某个数组是否包含给定的值

    推荐使用:可以用来判断一个值是否存在数组中



    let arr = [1, 2, 3, 4, 5]

    console.log(arr.includes(3)) // true

    console.log(arr.includes(0)) // false

    1

    2

    3

    十一、forEach()

    对数组进行遍历,对数组中的每一项运行给定函数,没有返回值



    forEarch(function (item, index, array) {})



    参数 item:表示数组中的每一项

    参数 index:表示数组中每一项对应的索引值

    参数 array:表示数组本身

    let arr = [1, 2, 3, 4, 5]

    arr.forEach((item, index, array) => {

    console.log(item + '---' + index + '---' + (arr === array))

    })

    1

    2

    3

    4

    十二、map() -----> 不会改变原数组

    map() 方法是将数组中的每一项调用提供的函数,结果返回一个新数组,并没有改变原来的数组

    映射



    let arr = [1, 2, 3, 4, 5]

    let newArr = arr.map(item => item * item)



    console.log(newArr) // [1, 4, 9, 16, 25]

    console.log(arr) // [1, 2, 3, 4, 5]

    1

    2

    3

    4

    5

    十三、filter() -----> 不会改变原数组

    filter() 方法是将数组中所有的元素进行判断,将满足条件的元素作为一个新数组返回

    过滤



    let arr = [12, 17, 26, 520, 1314]

    let newArr = arr.filter((item, index) => {

    return item > 20

    })

    console.log(newArr) // [26, 520, 1314]

    1

    2

    3

    4

    5

    十四、every()

    every() 判断数组中每一项都是否满足条件,只有所有项都满足条件才返回 true,否则返回 false

    let arr = [1, 2, 3, 4, 5]

    let boolean1 = arr.every(item => item > 0)

    let boolean2 = arr.every(item => item > 3)



    console.log(boolean1) // true

    console.log(boolean2) // false

    1

    2

    3

    4

    5

    6

    十五、some()

    some() 判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回 true,否则返回 false

    let arr = [1, 2, 3, 4, 5]

    let boolean3 = arr.some(item => item > 3)

    let boolean4 = arr.some(item => item < 0)



    console.log(boolean3) // true

    console.log(boolean4) // false

    1

    2

    3

    4

    5

    6

    十六、reduce() 和 reduceRight()

    reduce() 方法是所有元素调用返回函数,返回值为最后结果,传入的值必须是函数类型

    接受两个参数:每一项调用的函数和作为归并基础的初始值(可选项)

    这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。



    // 利用 reduce() 方法实现数组求和,给数组一开始家里一个初始值 3

    let arr = [1, 2, 3, 4, 5]

    let sum = arr.reduce((prev, cur, index, array) => {

    // 函数接受 4 个参数:

    // 前一个值、当前值、项的索引值、原数组对象

    console.log(prev, '---', cur, '---', index, '---', array)

    return prev + cur

    }, 3)

    console.log(sum) // 18 = 15 + 3

    1

    2

    3

    4

    5

    6

    7

    8

    9

    与之相对应的还有一个 Array.reduceRight() 方法,区别是这个是从右向左操作的



    十七、Array.from() 将类数组转化为数组

    let arrayLike = {

    '0': 'a',

    '1': 'b',

    '2': 'c',

    '3': 'd',

    length: 4

    }

    // ES5 写法

    let arr1 = [].slice.call(arrayLike) // ['a', 'b', 'c', 'd']



    // ES6

    let arr2 = Array.from(arrayLike) // ['a', 'b', 'c', 'd']

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    十八、Array.of() 方法用于将一组值转化为数组

    Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。



    Array.of(1, 2, 3, 4, 5) // [1, 2, 3, 4, 5]

    Array.of('abcd') // ['abcd']

    Array.of('abcd').length // 1

    Array.of() // []



    // Array.of 方法的实现

    function ArrayOf () {

    return [].slice.call(arguments)

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    十九、数组实例的 find() 和 findIndex()

    数组实例的 find() 方法,用于找出第一个符合条件的数组成员

    它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为 true 的成员,然后就返回该成员,如果没有符合条件的成员,则返回 undefined

    let arr = [1, 2, 3, 4, 5]

    let value= arr.find((item, index, array) => {

    // item 表示循环遍历数组的每一项

    // index 每一项对应的索引值

    // array 原数组对象

    return item > 3

    })

    console.log(value) // 4

    console.log(arr) // [1, 2, 3, 4, 5]



    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    数组实例的 findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回 -1

    let arr = [1, 2, 3, 4, 5]

    let index = arr.findIndex((item, index, array) => {

    return item > 3

    })



    console.log(index) // 3



    [NaN].indexOf(NaN) // -1

    [NaN].findIndex(value => Object.is(NaN, value)) // 0

    [NaN].includes(NaN) // true

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    由此可见:一般用来判断数组中是否存在某个值,推荐使用 includes



    二十、扁平化数组 flat() 方法 -----> 不会改变原数组

    let arr = [1, [2, 3, [4, 5, [6]]]]

    let arrFlat = arr.flat(Infinity)

    console.log(arrFlat) // [1, 2, 3, 4, 5, 6]

    console.log(arr) // [1, [2, 3, [4, 5, [6]]]]

    1

    2

    3

    4

    利用递归实现数组扁平化



    let arrayFlat = []

    let myFlat = (arr) => {

    for (let i = 0; i < arr.length; i++) {

    let item= arr[i]

    // 判断 arr[i] 是否是数组

    if (Array.isArray(item)) {

    // 如果是数组,继续调用函数 myFlat

    myFlat(item)

    } else {

    arrayFlat.push(item)

    }

    }

    return arrayFlat

    }



    蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

彻底解决小程序无法触发SESSION问题

seo达人

一、首先找到第一次发起网络请求的地址,将服务器返回set-cookie当全局变量存储起来

wx.request({
  ......
  success: function(res) {
    console.log(res.header);
    //set-cookie:PHPSESSID=ic4vj84aaavqgb800k82etisu0; path=/; domain=.fengkui.net

    // 登录成功,获取第一次的sessionid,存储起来
    // 注意:Set-Cookie(开发者工具中调试全部小写)(远程调试和线上首字母大写)
    wx.setStorageSync("sessionid", res.header["Set-Cookie"]);
  }
}) 

二、请求时带上将sessionid放入request的header头中传到服务器,服务器端可直接在cookie中获取

wx.request({
  ......
  header: {
    'content-type': 'application/json', // 默认值
    'cookie': wx.getStorageSync("sessionid")
    //读取sessionid,当作cookie传入后台将PHPSESSID做session_id使用
  },
  success: function(res) {
    console.log(res)
  }
}) 

三、后台获取cookie中的PHPSESSID,将PHPSESSID当作session_id使用

<?php
// 判断$_COOKIE['PHPSESSID']是否存在,存在则作session_id使用
if ($_COOKIE['PHPSESSID']) {
    session_id($_COOKIE['PHPSESSID']);
}

session_start();
echo session_id(); 

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档