关于url:链接的参数

var test = window.location.hash; 169=83&172=137

January 30, 2023 · 1 min · jiezi

关于url:yarl-PK-python3-标准库-urllibqbit

前言测试环境 Python 3.8yarl 1.8.1本文次要是绝对比易用性,无关性能yarl 官网文档:https://yarl.aio-libs.org/en/...url 组成部分yarl VS. urllib获取 url 参数urllib>>> from urllib import parse>>> url = r'https://docs.python.org/3.8/search.html?q=parse&check_keywords=yes&area=default'>>> parseResult = parse.urlparse(url)>>> parseResultParseResult(scheme='https', netloc='docs.python.org', path='/3.8/search.html', params='', query='q=parse&check_keywords=yes&area=default', fragment='')>>> param_dict = parse.parse_qs(parseResult.query)>>> param_dict{'q': ['parse'], 'check_keywords': ['yes'], 'area': ['default']}>>> q = param_dict['q'][0]>>> q'parse'#留神:加号会被解码,可能有时并不是咱们想要的>>> parse.parse_qs('proxy=183.222.102.178:8080&task=XXXXX|5-3+2'){'proxy': ['183.222.102.178:8080'], 'task': ['XXXXX|5-3 2']}如果你还想问为什么没有 urldecode,把下面的示例看五遍。^_^ yarl>>> url = URL(r"https://docs.python.org/3.8/search.html?q=parse&q=1&check_keywords=yes&area=default")>>> url.query["q"]'parse'# 多值时能够用 getall 函数>>> url.query.getall("q") ['parse']解析 url 的 query stringurllib>>> from urllib import parse>>> parse.parse_qs('action=addblog&job=modify&tid=1766670') # 1{'tid': ['1766670'], 'action': ['addblog'], 'job': ['modify']} #留神和第3个并不一样>>> parse.parse_qsl('action=addblog&job=modify&tid=1766670')[('action', 'addblog'), ('job', 'modify'), ('tid', '1766670')] # 3>>> dict(parse.parse_qsl('action=addblog&job=modify&tid=1766670')) #留神和第1个并不一样{'tid': '1766670', 'action': 'addblog', 'job': 'modify'}yarl>>> url = URL.build(query_string="action=addblog&job=modify&tid=1766670")>>> url.query<MultiDictProxy('action': 'addblog', 'job': 'modify', 'tid': '1766670')>>>> url.query['tid']'1766670'encode 编码urllib>>> from urllib import parse>>> query = { 'name': 'walker', 'age': 99, }>>> parse.urlencode(query)'name=walker&age=99'yarlfrom yarl import URL>>> query = { 'name': 'walker', 'age': 99, }>>> url = URL.build(query=query)>>> url.query_string'name=walker&age=99'quote 编码urllib>>> from urllib import parse>>> parse.quote('a&b/c') #未编码斜线'a%26b/c'>>> parse.quote_plus('a&b/c') #编码了斜线'a%26b%2Fc'yarlyarl 仿佛无此性能unquote 解码urllibfrom urllib import parse>>> parse.unquote('1+2') #不解码加号'1+2'>>> parse.unquote('1+2') #把加号解码为空格'1 2'域名编码防止敏感词屏蔽>>> ''.join('%' + ('%x'%ord(ch)).upper() for ch in 'github.com')'%67%69%74%68%75%62%2E%63%6F%6D'本文出自 qbit snap

October 24, 2022 · 1 min · jiezi

关于url:BUGurl-参数-AES-加密和解密问题

原文地址: 【BUG】url 参数 AES 加密和解密问题 欢送拜访我的博客: http://blog.duhbb.com/ 引言bug 复盘, 让你少写 bug! 明天剖析的是一个 url 参数加密解密的问题, 起因毁坏了加密后的字符串导致解密失败. 参数的加密解密状况形容url 有个参数是地址, 比方 http://www.hello.com/, 申请这个 url 的时候试图把最初的正斜杠给 trim 掉. 当初有个平安问题须要将这个地址参数给加密, 而加密后的字符串尾部可能呈现 /. 所以解决这个问题的时候肯定要留神: 加密之前能够 trim加密之后的字符串不能再 trim 了, 否则加密的后果不残缺同理 解密之前的字符串是不能 trim 的解密之后的字符串能够 trim 的为什么始终没有暴露出这个问题呢? 起因是, 加密的盐值是用了日期, 导致 / 的呈现是个概率问题, 摸不准那天就触发了这个雷了. 问题起因如上, 就是因为解密的时候没有判断是否启用了加密, 而先去 trim 而后在解密, 会导致如果加密字符串尾部有 /, 最初解密的加密字符串是不对的. 正斜杠 / 须要本义吗?Chrome + SpringBoot 测试?a=/sdfsdf/sdfsf&b=/ 这种组合的话在 Spring 中是能够获取到带 / 的 a 和 b 的值的. 用 %2F 或者 %2f 的话也能够获取 / 参数, emmmmm. ...

June 15, 2022 · 1 min · jiezi

关于url:2021年最新获取url参数的方法用正则就落后啦

前言:置信大家对获取浏览器参数都很相熟,第一反馈是应用正则表达式去对浏览器的参数进行切割获取,然而浏览器曾经提供了一个URLSearchParams这个接口给咱们去操作URL的查问字符串 应用正则表达式获取url温故而知新,先上一下咱们惯例应用正则表达式去获取url参数的代码 function getParams(url, params){ var res = new RegExp("(?:&|/?)" + params + "=([^&$]+)").exec(url); return res ? res[1] : '';} // url: xx.com?id=2&isShare=trueconst id = getParams(window.location.search, 'id') console.log(id) // 2复制代码然而,当初再也不必正则这么简单去获取浏览器的查问参数啦,浏览器给咱们间接提供了一个URLSearchParams接口,让咱们能够对查问参数有很大的操作空间,而且比起之前应用正则,更加简洁间接 对于URLSearchParams办法代码实现首先把怎么应用URLSearchParams办法实现获取url参数的代码呈上 const urlSearchParams = new URLSearchParams(window.location.search);const params = Object.fromEntries(urlSearchParams.entries()); console.log(params) // {id: '2', isShare: 'true'}console.log(params.id) // 2复制代码是不是超级简略,只须要以url作为参数传入,并且创立URLSearchParams的一个实例对象,而后调用entries()这个办法,返回一个迭代协定iterator,该协定反对能够遍历所有反对健/值对的列表 此时还须要通过Object.fromEntries()这个办法去把该健/值对的列表,而后咱们就能够欢快地应用获取到的参数啦 URLSearchParams的兼容性搜了一下URLSearchParams的兼容性查问,详情请点击 IE真的是万恶之源,其余古代浏览器的兼容性都杠杠的,如果是不须要兼容IE的我的项目,能够释怀食用 如果切实要兼容IE,也不要怕,能够应用url-search-params-polyfill这个插件去应用啦 装置形式: npm install url-search-params-polyfill --save复制代码应用形式: const params = new URLSearchParams("id=2&isShare=true");复制代码最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: https://gitee.com/ZhongBangKe...不胜感激 !

November 13, 2021 · 1 min · jiezi

关于url:转载阮一峰关于URL编码

一、问题的由来URL就是网址,只有上网,就肯定会用到。 一般来说,URL只能应用英文字母、阿拉伯数字和某些标点符号,不能应用其余文字和符号。比方,世界上有英文字母的网址"http://www.abc.com",然而没有希腊字母的网址"http://www.a.com"(读作阿尔法-贝塔-伽玛.com)。这是因为网络规范RFC 1738做了硬性规定: "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL.""只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*'(),"[不包含双引号]、以及某些保留字,才能够不通过编码间接用于URL。"这意味着,如果URL中有汉字,就必须编码后应用。然而麻烦的是,RFC 1738没有规定具体的编码方法,而是交给应用程序(浏览器)本人决定。这导致"URL编码"成为了一个凌乱的畛域。 上面就让咱们看看,"URL编码"到底有多凌乱。我会顺次剖析四种不同的状况,在每一种状况中,浏览器的URL编码方法都不一样。把它们的差别解释分明之后,我再说如何用Javascript找到一个对立的编码方法。 二、状况1:网址门路中蕴含汉字关上IE(我用的是8.0版),输出网址http://zh.wikipedia.org/wiki/春节。留神,春节这两个字此时是网址门路的一部分。 查看HTTP申请的头信息,会发现IE理论查问的网址是http://zh.wikipedia.org/wiki/%E6%98%A5%E8%8A%82。也就是说,IE主动将"春节"编码成了%E6%98%A5%E8%8A%82。 咱们晓得,"春"和"节"的utf-8编码别离是E6 98 A5和E8 8A 82,因而,%E6%98%A5%E8%8A%82就是依照程序,在每个字节前加上%而失去的。(具体的转码办法,请参考我写的《字符编码笔记》。) 在Firefox中测试,也失去了同样的后果。所以,论断1就是,网址门路的编码,用的是utf-8编码。 三、状况2:查问字符串蕴含汉字在IE中输出网址http://www.baidu.com/s?wd=春节。留神,"春节"这两个字此时属于查问字符串,不属于网址门路,不要与状况1混同。 查看HTTP申请的头信息,会发现IE将春节转化成了一个乱码。 切换到十六进制形式,能力分明地看到,"春节"被转成了B4 BA BD DA。 咱们晓得,春和节的GB2312编码(我的操作系统"Windows XP"中文版的默认编码)别离是B4 BA和BD DA。因而,IE实际上就是将查问字符串,以GB2312编码的格局发送进来。 Firefox的解决办法,略有不同。它发送的HTTP Head是wd=%B4%BA%BD%DA。也就是说,同样采纳GB2312编码,然而在每个字节前加上了%。 所以,论断2就是,查问字符串的编码,用的是操作系统的默认编码。 四、状况3:Get办法生成的URL蕴含汉字后面说的是间接输出网址的状况,然而更常见的状况是,在已关上的网页上,间接用Get或Post办法收回HTTP申请。 依据台湾中兴大学吕瑞麟老师的试验,这时的编码方法由网页的编码决定,也就是由HTML源码中字符集的设定决定。 <meta http-equiv="Content-Type" content="text/html;charset=xxxx">如果下面这一行最初的charset是UTF-8,则URL就以UTF-8编码;如果是GB2312,URL就以GB2312编码。 举例来说,百度是GB2312编码,Google是UTF-8编码。因而,从它们的搜寻框中搜寻同一个词"春节",生成的查问字符串是不一样的。 百度生成的是%B4%BA%BD%DA,这是GB2312编码。 Google生成的是%E6%98%A5%E8%8A%82,这是UTF-8编码。 ...

June 26, 2021 · 1 min · jiezi

关于url:简述字符集与编码

因为计算机外部只能辨认和解决二进制代码,所以字符都必须依照肯定的规定用一组二进制编码来示意。 在学习编码之前,须要先理解一下 字符集与编码的关系:字符集(Character Set)是字符的汇合,定义零碎能解决哪些字符;编码(Encoding)则规定这些字符在计算机外部的示意形式。 字符编码ASCII码(编码字符集)目前,国内上广泛采纳的一种字符零碎是7位二进制编码的ASCII码,它可示意10个十进制数码、52 个英文大写字母和小写字母(A~Z, a~z)及肯定数量的专用符号(如$、%、+、=等),共128个字符。为了存入计算机,通常最高位补0,凑足1B。 在ASCII码中,编码值0~31为控制字符,用于通信管制或设施的性能管制;编码值32~126共95个字符称为可印刷字符;编码值127是DEL码。 0~9的ASCII码值为48(0110000)~57(0111001),即去掉高3位,只保留低4位,正好是二进制模式的0-9。因为ASCII码的局限性,各国的语言不能残缺地示意进去。于是对 ASCII 字符集做了拓展。 汉字的示意和编码目前采纳 GB 2312-80规范 : 汉字+各种符号共7445个。用两个字节示意一个汉字,每字节用七位码。(1个汉字相当于两个英文字符) 规定:ASCII 值小于 127 的字符的意义与原来 ASCII 集中的字符雷同,但当两个 ASCII 值大于 127 的字符连在一起时,就示意一个简体中文的汉字。 为了在解码时操作的对立,在 ASCII 里原本就有的数字、标点、字母都对立从新示意为了两个字节长的编码,这就是常说的 “全角” 字符,而原来在 127 号以下的就叫 “半角” 字符。 汉字编码包含:输出编码 区位码国标码汉字内码汉字字形码区位码:94个区,每区94个地位。是4位十进制数,前2位是区码,后2位是位码。国标码:将十进制的区位码转换成十六进制数后,再在每字节上加上20H。国标码两字节的最高位都是0。汉字内码:为了不便计算机辨别中文字符和英文字符,将国标码两字节最高位都改为“1“,这就是汉字内码。 GBKGBK 是对 GB2312 的一个扩大,兼容 GB2312,因而也兼容 ASCII,也是一个变长编码方案。上面是一个简介: GBK 总体编码范畴为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,总计 23940 个码位,共支出 21886 个汉字和图形符号,其中汉字(包含部首和构件)21003 个,图形符号 883 个。GBK 是国家有关部门与一些信息行业企业等一起单干推出的计划,但并未作为国家标准公布,只是一个事实上的规范,一个过渡计划,为 GB18030 规范作的一个筹备。 世界上各国都有不同的编码方式,0—127 示意的符号仍然都是一样的,因为他们都兼容 ASCII 码,但127之后的同一个二进制数字能够被解码成不同的符号。因而,要想关上一个文本文件,就必须晓得它的编码方式,否则用谬误的编码方式解读,就会呈现乱码。 Unicode把所有语言都对立到一套编码里,且兼容 ASCII。 ASCII、GBK 等类编码模式的字符集和编码方式都是一一对应的,Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。 ...

March 8, 2021 · 2 min · jiezi

一个-URL-的自述

苏醒虽说现在是凌晨 3 点,但 acohome.cn 所在的服务器却收到了一个请求:http://acohome.cn 。伴随着警报响起,睡梦中的服务器冷不防打了个激灵。 “快告诉我,你的传输协议是什么?” “咦?你是在问我吗?” 我回答道。 “这里只有你一个,难不成我问空气?哦这里空气是比较稀薄,你还好吧?” 服务器见我迷迷糊糊的样子问道。 “我是谁,我在哪里?” 刚睡醒的我有点失忆。 “你是一个 URL,这是我的地盘,刚被网卡送到这,都忘了吗?” “哦,对,我是一个 URL 大概 10 毫秒前被浏览器创建,并送出,终于到你这啦,这是我的传输协议 HTTP 给你。” 在经历了一次长眠后,我想起了自己的使命,去服务器要一张网页。 “好,HTTP 服务,你过来下,这里有你的请求,快来领走。” 在得到我的传输协议后,服务器向 HTTP 服务喊道,语气显有点不耐烦,可能是因为我的短暂失忆让他有点生气了。 “赶紧的,起来干活了,这么早就有请求过来了,还让不让人休息了。” 服务器在 HTTP 服务没过来之前,又咕哝了一句。 我在一旁瑟瑟发抖,我已经记起了我的使命,只希望 HTTP 服务早点过来。过了不久,HTTP 服务走了过来。 “速度点,跟我过来!” HTTP 服务也没好气的说道。 使命跟着 HTTP 服务来到了一个陌生的环境,里面高高挂着 80 443 8080 8000,4 个牌子。 “你端口号是多少?” 一摸口袋,竟然找不到端口号,心中一虚,吞吞吐吐道 “那个,我好像没有端口号。” “没有就没有” 看到我吞吞吐吐的样子,HTTP 服务更不耐烦了,但手上的动作却没停,狠狠的拉了一下 80 的牌子,然后头也不回的走了。 “来了来了” 80 牌子的另一头响起一个略微耳熟的声音,不一会来了一个人。 虽说看起来有点陌生,但却看到了熟悉的身影,我赶忙过去打了声招呼。 “Hi JavaScript 你怎么也在这啊?” “咦?你是谁,你怎么认识我?” 突然间,我想起这是服务器,它不可能是我认识的那个人。 “我认识一个长的很像你的人,生活在浏览器的那个?我刚从那边过来。” “哦~ 那是我哥。我和他不熟。” ...

October 17, 2019 · 1 min · jiezi

浅析URL

浅析URLURL概览URL:Uniform Resource Locator的缩写。译为“统一资源定位符”URL的组成:协议+域名+端口+路径+查询参数+锚点URL举例:https://www.baidu.com/s?wd=he... 协议:https域名:www.baidu.com路径/s:查询参数:wd=hello&rsv_spt=1锚点:#5(不在network中显示,只和本地有关)端口:443(默认)IPInternet protocol:网络协议李爵士发明的三样东西: www(万维网):URL+HTTP+HTMLIP的两个作用 定位一台设备定义了如何封装数据,以及和其他设备交流(一)外网IP 路由器连上电信的服务器,那么路由器就会有一个外网IP;如果重启路由器,就有可能被分配到一个新的IP:也就是说没有固定的外网IP(二)内网IP 路由器会创建一个内网,并给自己分配一个好记的域名,一般是192.168.1.1路由器会给每个连接路由器的设备分配一个IP(三)路由器的功能: 内网中的设备可以互相访问,但不能直接访问外网。想要访问外网就必须通过路由器外网中的设备也可以互相访问,但不能直接访问内网,想要把内容送到内网,也需要通过路由器内网和外网是两个独立的空间,无法互通,唯一的联通点就是路由器路由器有时候也被叫做网关(四)几个特殊的IP 127.0.0.1 表示自己localhost表示hosts指定为自己0.0.0.0不表示任何设备端口一台机器可以提供很多服务:每个服务一个号码,这个号码叫做端口号port一台机器可以提供不同的服务: HTTP服务:使用80端口HTTPS服务:使用443端口FTP服务:使用21端口一共65535个端口端口使用的规则 0到1023号端口是留给系统用的你只有拥有了管理员 权限后,才能使用1024个系统端口,其他端口可以给用户使用比如http-server默认使用8080端口一个端口如果被占用,那么只能使用另一个端口tips: 端口和IP缺一不可 域名域名就是IP的别称记忆点:(1)一个域名可以对应不同IP(均衡负载)(2)一个IP可以对应不同域名(共享主机)(3)均衡负载:防止一台机器扛不住(4)共享主机:穷开发者会这么做,公用一个主机 域名和IP是如何对应起来的?——DNSDNS(Domain Name System, 域名系统/域名服务)当输入baidu.com并点击回车: 你的浏览器向电信/联通提供的DNS服务器询问www.baidu.com对应什么IP电信/联通会回答一个IP浏览器向对应的443/80端口发送请求请求内容为baidu.com的首页为什么是80、443端口? 服务器默认用80端口提供http服务服务器默认用443端口提供https服务可以在开发者工具中看到具体的端口(network)域名等级和wwwcom是顶级域名baidu.com是二级域名www.baidu.com是三级域名 www多余吗? 非常多余理论上讲xxx.com和www.xxx.com可以对应不同的公司如何查看域名对应的IP地址?在命令行中输入ping xxx即可得到xxx域名对应的IP地址了在命令行中输入nslookup xxx就可以看到xxx域名对应的所有地址了 http相关概念HTTP全称:HyperText Transfer ProtocolHTTP作用:规定请求的格式和响应的格式

October 5, 2019 · 1 min · jiezi

使用-wbr-解决长-URL-的换行问题

问题我们知道,世界上文字主要有两种:一种是以中文为代表的象形文字;另一种是以英法俄等为代表的拼音语系。前者的换行很简单,每个单字都有自己的意义,所以每个字后面都可以换行。拼音语言,字母组合本身无意义,连在一起才有意义;不同单词意义差异巨大,所以只能以单词为单位换行。 Web 开发中,屏幕宽度有限,超长文字必须换行。在 CSS 中,控制换行的属性主要有 word-break,white-space,其中,默认换行行为的是 word-break: normal,即以单词为单位换行。比较奇怪的是,对于 URL,我本以为类似 /.:?& 都是明显的单词分隔符,理应换行,但实际上,浏览器并不会在这些地方换行。如果我们使用 break-all 或者 break-word,则会使得浏览器在不合理的地方换行,如果刚好在表格里,别的列内容比较多,那么包含 URL 的单元格就会被挤压得非常窄,拉得特别高,非常难看,非常难读。 尝试原生方法无法解决问题,只好摸索手动断行的做法。但是想完美解决问题非常困难: 第一个方案是全部换行,肯定不行; 第二个方案固定宽度换行,因为表格内容不固定,效果也很差,也不行; 老板提出了第三个方案:使用“8.3”格式,即超长字符串只保留前8个字符,后面显示“...",然后可以手动展开。很明显,这个方案对 URL 来说没有什么价值,https:// 加起来正好 8 个字符,有意义么……即使加长也一样,因为用户有时候看域名,有时候看 pathname,也有时候看 search,我们没有办法预测。 然后老板又提出“Excel 方案”,即固定列宽,自动隐藏超出的文字,用户可以通过拖拽来调整列宽。这个方案理论上可以解决问题,但是实现难度太大,因为浏览器自带表格自适应宽度的算法,采用 “Excel 方案” 就必须放弃这个算法自己手动实现,成本很高,非万不得已也不想做。 最后,动态换行,根据表格宽度计算在哪里断行。还是不行,计算难度太大。 用 <wbr> 解决这个问题困扰了我很久,直到前两天,我突然发现原来有 <wbr> 软换行的存在。而且它的兼容性非常之好,甚至连 IE8 都支持。 它的含义是“可换可不换”。当元素宽度不够需要换行,就从它这里换;如果宽度够,就不换行。所以,只需要在“可能”换行的地方加上这个元素,就可以达成我的目标。写成代码很简单,大约是这样: function wrapUrl(url) { if (!url) { return ''; } // 先把协议取出来,我不希望在协议这里换行 const head = url.substring(0, 10); const left = url.substring(10); // 在 `?&amp;/` 前面插入 `&lt;wbr>` // 或者16个连续英文数字也要换行,打断 hash 和 md5 return head + left.replace(/([?&amp;\/]|([a-zA-Z0-9]{16}))/g, str => '&lt;wbr>' + str );}实际效果很好,大概是这样(截图时,<wbr> 放在断开位置的后面,我觉得不好看,就调整了下): ...

June 1, 2019 · 1 min · jiezi

如何查找SAP-Fiori-launchpad-Designer的准确路径即url地址

比如我们知道在SPRO里下面这个路径的customizing activity里打开Fiori Launchpad designer: SAP Netweaver->UI technologies->SAP Fiori->Configure Launchpad content->Adding Apps to SAP Fiori Launchpad->Configure Target Mappings and Tiles->SAP Fiori Launchpad Designer, 点右键,选择Display technical info: 找到这个activity绑定的事务码为/UI2/FLPD_CUST: SE93里查到这个事务码绑定的report名称为/UI2/START_URL: 这个报表执行后的界面: Fiori Launchpad designer的准确路径可以通过调试获得,存储于变量gv_url里: 要获取更多Jerry的原创文章,请关注公众号"汪子熙":

June 1, 2019 · 1 min · jiezi

浅谈encodeURI和encodeURIComponent

encodeURI 区别于 encodeURIComponent对URL编码是常见的事,所以这两个方法应该是实际中要特别注意的。它们都是编码URL,唯一区别就是编码的字符范围,其中 encodeURI方法不会对下列字符编码:ASCII字母、数字、~!@#$&*()=:/,;?+'encodeURIComponent方法不会对下列字符编码:ASCII字母、数字、~!*()'所以encodeURIComponent比encodeURI编码的范围更大。实际例子来说,encodeURIComponent会把 http:// 编码成 http%3A%2F%2F 而encodeURI却不会。 二者应用场景如果你需要编码整个URL,然后需要使用这个URL,那么用encodeURI;比如:encodeURI("http://www.cnblogs.com/season-huang/some other thing");编码后会变为: "http://www.cnblogs.com/season-huang/some%20other%20thing";其中,空格被编码成了%20。但是如果你用了encodeURIComponent,那么结果变为:"http%3A%2F%2Fwww.cnblogs.com%2Fseason-huang%2Fsome%20other%20thing" 看到了区别吗,连 "/" 都被编码了,整个URL已经没法用了。 当你需要编码URL中的参数的时候,那么encodeURIComponent是最好方法。var param = "http://www.cnblogs.com/season-huang/"; //param为参数param = encodeURIComponent(param);var url = "http://www.cnblogs.com?next=" + param;console.log(url) //"http://www.cnblogs.com?next=http%3A%2F%2Fwww.cnblogs.com%2Fseason-huang%2F"看到了把,参数中的 "/" 可以编码,如果用encodeURI肯定要出问题,因为后面的/是需要编码的。

April 27, 2019 · 1 min · jiezi

web开发中URL编码简介

一、为什么要 urlencode()?因为当字符串数据以url的形式传递给web服务器时,字符串中是不允许出现空格和特殊字符的。也就是说,url的参数传递的时候,需要遵循一定的url规范才能正确的传送。通常如果一样东西需要编码,说明这样东西并不适合传输。原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义。大部分需要编码的原因是由于有特殊字符(如@、#、&等)或者参数是中文形式。Url编码的原则就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。二、javascript中编码的函数escape() 方法:(1)采用ISO Latin字符集对指定的字符串进行编码。(2)所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。(3)比如,空格符对应的编码是%20。(4)不会被此方法编码的字符: @ * / +encodeURI() 方法:(1)把URI字符串采用UTF-8编码格式转化成escape格式的字符串。(2)不会被此方法编码的字符:! @ # $& * ( ) = : / ; ? + ’encodeURIComponent() 方法:(1)把URI字符串采用UTF-8编码格式转化成escape格式的字符串。(2)与encodeURI()相比,这个方法将对更多的字符进行编码,比如 / 等字符。(3)所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。(4)不会被此方法编码的字符:! * ( ) ‘重点:(1)因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面的charset是一致的时候),只需要使用 escape。(2)如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用encodeURI或者 encodeURIComponent。(3)另外,encodeURI/encodeURIComponent是在javascript1.5之后引进的,escape则在javascript1.0版本就有。三、php中关于编码的函数主要是urlencode和urldecode其他的参考:https://www.cnblogs.com/xuey/…四、划重点url的编码是为了让一些特殊字符以及中文能够通过编码转换成安全的字符传递,使之符合url标准。大部分的js中编码函数多使用encodeURIComponent,因为该函数是编码范围最大的函数。但是还需要根据业务需求选择不同的编码函数。五、参考链接https://www.cnblogs.com/liuho…

March 29, 2019 · 1 min · jiezi

详解vue中静态资源的路径问题(深度好文)

前言: node中的全局变量require开始前,咱们先聊聊node中require的用法。您可能觉得这有什么,不就是直接require(url)直接引用吗,如果您这么想,那可就太小看require了。let url = “@/assets/images/carousel/logo.svg"require(url) //报错let url = “logo.svg"require(”@/assets/images/carousel/"+url); //正确很诡异是不是? 我相信你第一次见到后会不自觉的说句f**k。这是因为你修改页面后,webpack进行编译,等待编译完,需要进行工程的打包,然后打包正确,才能热加载运行并刷新页面。如果require中传入的是个变量,它有可能是计算机系统中的任何目录下的任何文件,那么在打包静态资源时它有可能会将你的电脑整个磁盘遍历一遍(它很傻)。所以至少需要给出在哪个路径下,这样才能精确的将那个路径下的对应文件打包,然后在代码运行时,直接用对应文件名生成正则匹配(因为打包后的文件,可能有hash值。不能直接查文件名),找到后,加载到代码中。所以,请记住 尽可能详细的指定require中的路径,然后拼接变量接下来说下打包后的路径问题webpack将项目中的静态资源编译打包后,生成的路径已经不是原来的那个路径了。如src/assets/image/logo.jpg 编译后可能变成dist/public/image/logo.1d997ea3.jpg而通过require(“src/assets/image/logo.jpg”),会自动找到并加载dist/public/image/logo.1d997ea3.jpg文件一、<template>部分的路径处理Vue Loader 在编译单文件组件中的 <template> 块时,它也会将所有遇到的资源 URL 转换为 webpack 模块请求。(这样我们就没必要手动调用require了,而是交给vue-loader处理了)vue-loader默认可以处理的标签/特性的组合如下:{ video: [‘src’, ‘poster’], img: ‘src’, //即img元素上的src属性 source: ‘src’, //source元素上的src属性 image: ‘xlink:href’}面对上面的标签组合,vue-loader会自动进行资源url的转换。转换规则:a、如果路径是绝对路径,会被原样保留。如/src/assets/image/login/title.png//代码<template> <img src="/src/assets/image/login/title.png” alt=""></template>//渲染后html页面<img data-v-70c98a68="" src="/src/assets/image/login/title.png" alt="">//当然这个图片是无法展示的,因为编译后title.png已不在src/assets/image/login下了b、如果路径以 . 开头,将会被看作相对的模块依赖。如 ./titlea.png//代码<img src="./titlea.png" alt="">//渲染后html页面<img data-v-70c98a68="" src="/static/img/titlea.1e9fa570.png" alt="">c、如果路径以 @ 开头,也会被看作模块依赖。如果你的 webpack 配置中给 @ 配置了 alias,这就很有用了。所有 vue-cli 创建的项目都默认配置了将 @ 指向 /src//代码<img src="@/assets/image/login/title.png" alt="">//渲染后html页面<img data-v-70c98a68="" src="/static/img/title.1e9fa570.png" alt="">d、如果路径以 ~ 开头,其后的部分将会被看作模块依赖,既可以加载含有别名的静态资源,又可以加载node-modules中的资源。如//代码<img src="@/assets/image/login/title.png" alt="">//渲染后html页面<img data-v-70c98a68="" src="/static/img/title.1e9fa570.png" alt="">//代码<img src="[npm包名]/xxx/logo.png" alt="">//渲染后的html页面<img data-v-70c98a68="" src="/static/img/logo.2f53e458.png" alt="">二、<style>部分部分的路径处理由于vue-loader在处理style时,采用的是style-loader,所以可能 和上面<template>部分的转换规则不太一样。在vue-loader的内部使用了如下的配置(不一定配置,也有可能通过js直接给rules赋值)://在vue-loader的内部使用css-loadermodule.exports = { module: { rules: [ { test: /.css$/, loader: ‘css-loader’, options: { url: true, //默认选项 }, }, ], },};url为true时,则意味着可以将url中的字符串通过require()加载进来。转换规则//代码<style scoped>.login-wrap { background-image: url("/src/assets/image/login/title.png");}</style>//渲染后css.login-wrap[data-v-70c98a68] { background-image: url(/src/assets/image/login/title.png);}同样不会显示,编译后的路径不是这个b、如果路径以 . 开头,将会被看作相对的模块依赖。如 ./titlea.png//代码<style scoped>.login-wrap { background-image: url("./titlea.png");}</style>//渲染后css.login-wrap[data-v-70c98a68] { background-image: url(/static/img/titlea.1e9fa570.png);}c、如果路径以 ~ 开头,其后的部分将会被看作模块依赖,即可以加载含有别名的静态资源,又可以加载node-modules中的资源。如//代码<style scoped>.login-wrap { background-image: url("[npm包名]/logo.png");}</style>//渲染后css.login-wrap[data-v-70c98a68] { background-image: url(/static/img/logo.e05643fc.png);}//代码<style scoped>.login-wrap { background-image: url("@/assets/image/login/bg.png");}</style>//渲染后css.login-wrap[data-v-70c98a68] { background-image: url(/static/img/bg.1d997ea3.png);}注意: 和上面的<template>相比,唯独少了直接用@开头的方式url("@/assett/logo.png"),所以下面写法是错误的//代码<style scoped>.login-wrap { background-image: url("@/assets/image/login/bg.png");}</style>感谢各位看客的阅读,由于在项目中遇到了这样的困然,再加上同事也经常问我什么原因,故而填坑,以免其他人踩坑。 ...

March 12, 2019 · 1 min · jiezi

如何使用 JavaScript 解析 URL

在 Web 开发中,有许多情况需要解析 URL,这篇主要学习如何使用 URL 对象实现这一点。开始创建一个以下内容的 HTML 文件,并在浏览器中打开。<html> <head> <title>JavaScript URL parsing</title> </head> <body> <script> // 激动人心的代码即将写在这里 </script> </body></html>如果你想尝试本文中的任何内容,可以将其放在 <script> 标记中,保存,重新加载页面,看看会发生什么! 在本教程中,将使用 console.log 来打印所需要的内容,你可以打开开发都工具,来查看内容。什么是 URL这应该是相当简单的,但让我们说清楚。 URL 是网页的地址,可以在浏览器中输入以获取该网页的唯一内容。 可以在地址栏中看到它:URL 是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。此外,如果你不熟悉基本 URL 路径的工作方式,可以查看此文学习。URL 不都长的一样的这是一个快速提醒 - 有时 URL 可能非常奇怪,如下:https://example.com:1234/page/?a=bhttp://localhost/page.htmlhttps://154.23.54.156/page?x=…file:///Users/username/folder/file.png获取当前URL获取当前页面的 URL 非常简单 - 我们可以使用 window.location。试着把这个添加到我们形如写的的脚本中:console.log(window.location);查看浏览器的控制台:不是你想要的?这是因为它不返回你在浏览器中看到的实际 URL 地址——它返回的是一个 URL 对象。使用这个 URL 对象,我们可以解析 URL 的不同部分,接下来就会讲到。创建 URL 对象很快就会看到,可以使用 URL 对象来了解 URL 的不同部分。如果你想对任何 URL 执行此操作,而不仅仅是当前页面的 URL,该怎么办? 我们可以通过创建一个新的 URL 对象来实现。 以下是如何创建一个:var myURL = new URL(‘https://example.com’);就这么简单! 可以打印 myURL 来查看 myURL 的内容:console.log(myURL);出于本文的目的,将 myURL 设置为这个值:var myURL = new URL(‘https://example.com:4000/folder/page.html?x=y&a=b#section-2')将其复制并粘贴到 <script> 元素中,以便你可以继续操作! 这个 URL 的某些部分可能不熟悉,因为它们并不总是被使用 - 但你将在下面了解它们,所以不要担心!URL 对象的结构使用 URL 对象,可以非常轻松地获取 URL 的不同部分。 以下是你可以从 URL 对象获得的所有内容。 对于这些示例,我们将使用上面设置的 myURL。hrefURL 的 href 基本上是作为字符串(文本)的整个 URL。如果你想把页面的 URL 作为字符串而不是 URL 对象,你可以写 window.location.href。console.log(myURL.href);// Output: “https://example.com:4000/folder/page.html?x=y&a=b#section-2"协议 (protocol)URL的协议是一开始的部分。这告诉浏览器如何访问该页面,例如通过 HTTP 或 HTTPS。 但是还有很多其他协议,比如 ftp(文件传输协议)和 ws(WebSocket)。通常,网站将使用 HTTP 或 HTTPS。 虽然如果你的计算机上打开了文件,你可能正在使用文件协议! URL对象的协议部分包括:,但不包括 //。 让我们看看 myURL 吧!console.log(myURL.protocol);// Output: “https:“主机名(hostname)主机名是站点的域名。 如果你不熟悉域名,则它是在浏览器中看到的URL的主要部分 - 例如 google.com 或codetheweb.blog。console.log(myURL.hostname);// Output: “example.com"端口(port)URL 的端口号位于域名后面,用冒号分隔(例如 example.com:1234)。 大多数网址都没有端口号,这种情况非常罕见。 端口号是服务器上用于获取数据的特定“通道” - 因此,如果我拥有 example.com,我可以在多个不同的端口上发送不同的数据。 但通常域名默认为一个特定端口,因此不需要端口号。 来看看 myURL 的端口号:console.log(myURL.port);// Output: “4000"主机(host)主机只是主机名和端口放在一起,尝试获取 myURL 的主机:console.log(myURL.host);// Output: “example.com:4000"来源(origin)origin 由 URL 的协议,主机名和端口组成。 它基本上是整个 URL,直到端口号结束,如果没有端口号,到主机名结束。console.log(myURL.origin);// Output: “https://example.com:4000"pathname(文件名)pathname 从域名的最后一个 “/” 开始到 “?” 为止,是文件名部分,如果没有 “?” ,则是从域名最后的一个 “/” 开始到 “#” 为止 , 是文件部分, 如果没有 “?” 和 “#” , 那么从域名后的最后一个 “/” 开始到结束 , 都是文件名部分。console.log(myURL.pathname);// Output: “/folder/page.html"锚点(hash)从 “#” 开始到最后,都是锚部分。可以将哈希值添加到 URL 以直接滚动到具有 ID 为该值的哈希值 的元素。 例如,如果你有一个 id 为 hello 的元素,则可以在 URL 中添加 #hello 就可以直接滚动到这个元素的位置上。通过以下方式可以在 URL 获取 “#” 后面的值:console.log(myURL.hash);// Output: “#section-2"查询参数 (search)你还可以向 URL 添加查询参数。它们是键值对,意味着将特定的“变量”设置为特定值。 查询参数的形式为 key=value。 以下是一些 URL 查询参数的示例:?key1=value1&key2=value2&key3=value3请注意,如果 URL 也有 锚点(hash),则查询参数位于 锚点(hash)(也就是 ‘#’)之前,如我们的示例 URL 中所示:console.log(myURL.search);// Output: “?x=y&a=b"但是,如果我们想要拆分它们并获取它们的值,那就有点复杂了。使用 URLSearchParams 解析查询参数要解析查询参数,我们需要创建一个 URLSearchParams 对象,如下所示:var searchParams = new URLSearchParams(myURL.search);然后可以通过调用 searchParams.get(‘key’)来获取特定键的值。 使用我们的示例网址 - 这是原始搜索参数:?x=y&a=b因此,如果我们调用 searchParams.get(‘x’),那么它应该返回 y,而 searchParams.get(‘a’)应该返回 b,我们来试试吧!console.log(searchParams.get(‘x’));// Output: “y"console.log(searchParams.get(‘a’));// Output: “b"扩展获取 URL 的中参数方法一:正则法function getQueryString(name) { var reg = new RegExp(’(^|&)’ + name + ‘=([^&])(&|$)’, ‘i’); var r = window.location.search.substr(1).match(reg); if (r != null) { return unescape(r[2]); } return null;}// 这样调用:alert(GetQueryString(“参数名1”));alert(GetQueryString(“参数名2”));alert(GetQueryString(“参数名3”));方法二:split拆分法function GetRequest() { var url = location.search; //获取url中”?“符后的字串 var theRequest = new Object(); if (url.indexOf(”?”) != -1) { var str = url.substr(1); strs = str.split("&”); for(var i = 0; i < strs.length; i ++) { theRequest[strs[i].split("=”)[0]] = unescape(strs[i].split("=”)[1]); } } return theRequest;}var Request = new Object();Request = GetRequest();// var 参数1,参数2,参数3,参数N;// 参数1 = Request[‘参数1’];// 参数2 = Request[‘参数2’];// 参数3 = Request[‘参数3’];// 参数N = Request[‘参数N’];修改 URL 的中某个参数值//替换指定传入参数的值,paramName为参数,replaceWith为新值function replaceParamVal(paramName,replaceWith) { var oUrl = this.location.href.toString(); var re=eval(’/(’+ paramName+’=)([^&])/gi’); var nUrl = oUrl.replace(re,paramName+’=’+replaceWith); this.location = nUrl; window.location.href=nUrl}原文:https://codetheweb.blog/2019/…你的点赞是我持续分享好东西的动力,欢迎点赞!一个笨笨的码农,我的世界只能终身学习!更多内容请关注公众号《大迁世界》! ...

February 25, 2019 · 2 min · jiezi

Flutter路由管理代码这么长长长长长,阿里工程师怎么高效解决?(实用)

背景:在flutter的业务开发过程中,flutter侧会逐渐丰富自己的路由管理。一个轻量的路由管理本质上是页面标识(或页面路径)与页面实例的映射。本文基于dart注解提供了一个轻量路由管理方案。 不论是在native与flutter的混合工程,还是纯flutter开发的工程,当我们实现一个轻量路由的时候一般会有以下几种方法:较差的实现,if-else的逻辑堆叠: 做映射时较差的实现是通过if-else的逻辑判断把url映射到对应的widget实例上,class Router { Widget route(String url, Map params) { if(url == ‘myapp://apage’) { return PageA(url); } else if(url == ‘myapp://bpage’) { return PageB(url, params); } }}这样做的弊端比较明显: 1)每个映射的维护影响全局映射配置的稳定性,每次维护映射管理时需要脑补所有的逻辑分支. 2)无法做到页面的统一抽象,页面的构造器和构造逻辑被开发者自定义. 3)映射配置无法与页面联动,把页面级的配置进行中心化的维护,导致维护责任人缺失.一般的实现,手动维护的映射表: 稍微好一点的是将映射关系通过一个配置信息和一个工厂方法来表现class Router { Map<String, dynamic> mypages = <String, dynamic> { ‘myapp://apage’: ‘pagea’, ‘myapp://bpage’: ‘pageb’ } Widget route(String url, Map params) { String pageId = mypages[url]; return getPageFromPageId(pageId); } Widget getPageFromPageId(String pageId) { switch(pageId) { case ‘pagea’: return PageA(); case ‘pageb’: return PageB(); } return null; }在flutter侧这种做法仍然比较麻烦,首先是问题3仍然存在,其次是由于flutter目前不支持反射,必须有一个类似工厂方法的方式来创建页面实例。 为了解决以上的问题,我们需要一套能在页面级使用、自动维护映射的方案,注解就是一个值得尝试的方向。我们的路由注解方案annotation_route(github地址:https://github.com/alibaba-flutter/annotation_route)) 应运而生,整个注解方案的运行系统如图所示: 让我们从dart注解开始,了解这套系统的运作。dart注解注解,实际上是代码级的一段配置,它可以作用于编译时或是运行时,由于目前flutter不支持运行时的反射功能,我们需要在编译期就能获取到注解的相关信息,通过这些信息来生成一个自动维护的映射表。那我们要做的,就是在编译时通过分析dart文件的语法结构,找到文件内的注解块和注解的相关内容,对注解内容进行收集,最后生成我们想要的映射表,这套方案的构想如图示: 在调研中发现,dart的部分内置库加速了这套方案的落地。source_gendart提供了build、analyser、source_gen这三个库,其中source_gen利用build库和analyser库,给到了一层比较好的注解拦截的封装。从注解功能的角度来看,这三个库分别给到了如下的功能:build库:整套资源文件的处理analyser库:对dart文件生成完备的语法结构source_gen库:提供注解元素的拦截 这里简要介绍下source_gen和它的上下游,先看看我们捋出来的它注解相关的类图:source_gen的源头是build库提供的Builder基类,该类的作用是让使用者自定义正在处理的资源文件,它负责提供资源文件信息,同时提供生成新资源文件的方法。source_gen从build库提供的Builder类中派生出了一个自己的builder,同时自定义了一套生成器Generator的抽象,派生出来的builder接受Generator类的集合,然后收集Generator的产出,最后生成一份文件,不同的派生builder对generator的处理各异。这样source_gen就把一个文件的构造过程交给了自己定义的多个Generator,同时提供了相对build库而言比较友好的封装。 在抽象的生成器Generator基础上,source_gen提供了注解相关的生成器GeneratorForAnnotation,一个注解生成器实例会接受一个指定的注解类型,由于analyser提供了语法节点的抽象元素Element和其metadata字段,即注解的语法抽象元素ElementAnnotation,注解生成器即可通过检查每个元素的metadata类型是否匹配声明的注解类型,从而筛选出被注解的元素及元素所在上下文的信息,然后将这些信息包装给使用者,我们就可以利用这些信息来完成路由注解。annotation_route在了解了source_gen之后,我们开始着手自己的注解解析方案annotation_route 刚开始介入时,我们遇到了几个问题:只需要生成一个文件:由于一个输入文件对应了一个生成文件后缀,我们需要避免多余的文件生成需要知道在什么时候生成文件:我们需要在所有的备选文件扫描收集完成后再能进行映射表的生成source_gen对一个类只支持了一个注解,但存在多个url映射到一个页面 在一番思索后我们有了如下产出首先将注解分成两类,一类用于注解页面@ARoute,另一类用于注解使用者自己的router@ARouteRoot。routeBuilder拥有RouteGenerator实例,RouteGenerator实例,负责@ARoute注解;routeWriteBuilder拥有RouteWriterGenerator实例,负责@ARouteRoot注解。通过build库支持的配置文件build.yaml,控制两类builder的构造顺序,在routeBuilder执行完成后去执行routeWriteBuilder,这样我们就能准确的在所有页面注解扫描完成后开始生成自己的配置文件。 在注解解析工程中,对于@ARoute注解的页面,通过RouteGenerator将其配置信息交给拥有静态存储空间的Collector处理,同时将其输出内容设为null,即不会生成对应的文件。在@ARoute注解的所有页面扫描完成后,RouteWriteGenerator则会调用Writer,它从Collector中提取信息,并生成最后的配置文件。对于使用者,我们提供了一层友好的封装,在使用annotation_route配置到工程后,我们的路由代码发生了这样的变化: 使用前: class Router { Widget pageFromUrlAndQuery(String urlString, Map<String, dynamic> query) { if(urlString == ‘myapp://testa’) { return TestA(urlString, query); } else if(urlString == ‘myapp://testb’) { String absoluteUrl = Util.join(urlString, query); return TestB(url: absoluteUrl); } else if(urlString == ‘myapp://testc’) { String absoluteUrl = Util.join(urlString, query); return TestC(config: absoluteUrl); } else if(urlString == ‘myapp://testd’) { return TestD(PageDOption(urlString, query)); } else if(urlString == ‘myapp://teste’) { return TestE(PageDOption(urlString, query)); } else if(urlString == ‘myapp://testf’) { return TestF(PageDOption(urlString, query)); } else if(urlString == ‘myapp://testg’) { return TestG(PageDOption(urlString, query)); } else if(urlString == ‘myapp://testh’) { return TestH(PageDOption(urlString, query)); } else if(urlString == ‘myapp://testi’) { return TestI(PageDOption(urlString, query)); } return DefaultWidget; } }使用后:import ‘package:annotation_route/route.dart’; class MyPageOption { String url; Map<String, dynamic> query; MyPageOption(this.url, this.query); } class Router { ARouteInternal internal = ARouteInternalImpl(); Widget pageFromUrlAndQuery(String urlString, Map<String, dynamic> query) { ARouteResult routeResult = internal.findPage(ARouteOption(url: urlString, params: query), MyPageOption(urlString, query)); if(routeResult.state == ARouteResultState.FOUND) { return routeResult.widget; } return DefaultWidget; } }目前该方案已在闲鱼app内稳定运行,我们提供了基础的路由参数,随着flutter业务场景越来越复杂,我们也会在注解的自由度上进行更深的探索。关于annotation_route更加详细的安装和使用说明参见github地址:https://github.com/alibaba-flutter/annotation_route ,在使用中遇到任何问题,欢迎向我们反馈。本文作者:闲鱼技术-兴往阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 18, 2018 · 2 min · jiezi

Weex系列(2) —— 页面跳转和通信

Hello World项目之后就在想着这个系列接下来该怎么写,那就先简单拟个目录吧,一方面督促自己能坚持下去,一方面如果大家有兴趣的话,也请多多关注我的专栏,顺手点个赞啊~~目录Weex系列(序) —— 总要知道原生的一点东东(iOS)Weex系列(序) —— 总要知道原生的一点东东(Android)Weex系列(1) —— Hello World项目Weex系列(2) —— 页面跳转和通信[Weex系列(3) —— 单页面还是多页面][Weex系列(4) —— 老生常谈的三端统一][Weex系列(5) —— 封装原生组件和模块][Weex系列(6) —— css相关小结][Weex系列(7) —— web组件和webview][Weex系列(8) —— 是时候简析一下流程原理了][Weex系列(9) —— 踩坑填坑的集锦][Weex系列(10) —— 先这么多吧想到在写。。。]大致就是这个顺序吧,可能会微调,那下面就开始这一章吧。入口标题上加了官网怎么集成Weex到已有应用的链接,里面提到了很重要的入口方法。iOSNSURL *URL = [self testURL: [self.url absoluteString]];NSString *randomURL = [NSString stringWithFormat:@"%@%@random=%d",URL.absoluteString,URL.query?@"&":@"?",arc4random()];[_instance renderWithURL:[NSURL URLWithString:randomURL] options:@{@“bundleUrl”:URL.absoluteString} data:nil];这是前一篇用weex脚手架初始化的helloworld项目,在WXDemoViewController.m的render方法里面可以看到这段代码。然后重点来了,weex.config.bundleUrl的值:1、取得是上面options的bundleUrl值2、如果这个值不填,取得就是我们赋给renderWithURL的url地址。所以如果我们加载服务器上的一个页面js,然后这个页面又想跳回到本地的一个页面js,那么在服务器页面取bundleUrl的时候取得就是http的一个地址,是取不到我们想要跳到本地页面js绝对前缀地址的,有点绕,最后就讲讲我们App的思路吧。我做的两个App页面全部都是用vue写的,所以首页、tab页肯定的页面js肯定是的打在包里面的,我们也有做过拉新的活动页,这个页面就可以放在服务器上,支持热更新啊,就遇到了上面的跳转问题,我是全局取了一个bundlejs的绝对地址,在服务器上的页面也就是我们的拉新活动页面里面直接用这个地址就跳回到本地的页面了- (void)renderWithURL:(NSURL *)url options:(NSDictionary )options data:(id)data{ if (!url) { WXLogError(@“Url must be passed if you use renderWithURL”); return; } self.needValidate = [[WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)] needValidate:url]; WXResourceRequest request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; [self _renderWithRequest:request options:options data:data]; [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTNetworkHanding phase:WXTracingBegin functionName:@“renderWithURL” options:@{@“bundleUrl”:url?[url absoluteString]:@"",@“threadName”:WXTMainThread}];}Android可以在WXSDKInstance.java里面可以看到render(pageName,template,options,jsonInitData,flag);renderByUrl(pageName,url,options,jsonInitData,flag);安卓和iOS基本类似,但是这儿有两个方法,官网的文档是render,这一个render害死人啊,不过用weex脚手架初始化的项目用的是renderByUrl,所以如果官网直接用脚手架开发的,躲过一劫啊。可以看到这两个方法就差了第二个参数,下面是官网的代码,用render方法的时候,第二个参数里面得用WXFileUtils.loadFileContent这个方法,而且如果option不填的话bundleUrl是取不到js地址?后面我们加的参数的/ * WXSample 可以替换成自定义的字符串,针对埋点有效。 * template 是.we transform 后的 js文件。 * option 可以为空,或者通过option传入 js需要的参数。例如bundle js的地址等。 * jsonInitData 可以为空。 * width 为-1 默认全屏,可以自己定制。 * height =-1 默认全屏,可以自己定制。 */mWXSDKInstance.render(“WXSample”,WXFileUtils.loadFileContent(“hello.js”, this), null, null, -1, -1, WXRenderStrategy.APPEND_ASYNC);下面就来说说几种常见的跳转吧Native -> Weex也就是用开头我们提到的两个方法,然后把我们的bundlejs地址传入就可以打开Weex页面了Weex -> Native这个我这边用的很少,大概思路就是,拦截处理,iOS用Scheme、[[UIApplication sharedApplication] openURL:weburl];吧,Android用intent-filter吧。Weex -> Weex大家在我的helloworld那篇bundlejs小节里面有一个路径截图,可以对比代码参考一下,下面我也把iOS和Android的bundlejs路径图截出来了。const device = weex.config.env;getBaseUrl(url) { if (device.platform === ‘iOS’) { nativeBase = url.substring(0, bundleUrl.lastIndexOf(’/’) + 1); } else { nativeBase = ‘file://assets/dist/’; }}Weex页面A:Weex页面B的地址BUrl=getBaseUrl(weex.config.bundleUrl)+B.jsnavigator.push({url:BUrl}, function(e) {});webview -> Weex这也是比较常遇到的一个跳转,大概思路和Weex跳原生类似,也是一个拦截处理,这一块就放在后面Weex系列(7) —— web组件和webview这个章节讲吧。页面通信这块用的比较多的大概有三种。bundlejs路径地址传参就如标题描述的一样,weex.config.bundleUrl拿到类似A.js?a=1&b=2,和解析网页地址一样,拿到A传给B的a、b后面的值。BroadcastChannel我们在B页面操作完成之后,navigator.pop()之后回到A页面,希望A页面的button状态改变,因为页面是栈式操作,A页面不会自动刷新,可以用Weex提供的这个BroadcastChannel通道来解决,具体操作,大家点击标题就可以了解了。storage感觉这个大家应该非常熟悉,对,Weex也提供给我们了,我们可以愉快的在页面上使用了。globalevent最后还是提一下这个globalEvent,Weex和原生通过这个可以通信,这个我们用到的还是挺多的,大家也可以去官网了解一下呦。就这么多吧,欢迎大家关注我的专栏啊,如果有一点点喜欢,也请点个赞啊~ ...

November 14, 2018 · 1 min · jiezi