목차
总结
开发模式
localStorage的应用
事件管理
其他的一些
웹 프론트엔드 HTML 튜토리얼 好搜移动端页面研究_html/css_WEB-ITnose

好搜移动端页面研究_html/css_WEB-ITnose

Jun 24, 2016 am 11:14 AM

首先声明,我并不是好搜员工,研究源码只是爱好,并没有别的意思,下面的代码是在 pc-chrome模拟手机访问时截取的 m.so.com,并自己适当的修改了些变量名(因为源码被混淆、压缩了),只是学习用,如果有冒犯贵司之处,还请【联系我】 ,我会第一时间删除~

先看整个无缓存时的源码:源码部分变量我修改过,注释是我根据上下文添加的~

html<!Doctype html><!-- g-loading类让页面默认有个全局的loading图标,体验更友好,在下面页面会隐藏 --><!-- home_next应该属于某个js的埋点 --><html id=home_next class="g-loading" lang="zh-CN"><head><meta charset="UTF-8"><title>360搜索,SO靠谱</title><!-- 应该是速度上报勾子 --><script>wpo={p:"m_so",start:+(new Date),page:"home"}</script><!-- 页面全局变量 --><script> MSO = {}; SOH = {}; ENV = {}; <!-- 看样子应该部分变量是server端从ua中读取 --> ENV.android = '6_0'; ENV.webp = '1'; ENV.domain = 'so.com'; ENV.abv = 'a'; ENV.nat = '1'; ENV.brandname = '360'; ENV.sitename = '360搜索';</script><!-- 下面是ls缓存读取的核心js,会跟后端服务(判断是否有缓存而输出不同的html片段)有耦合 --><script>(function (e, document) { // 查找id元素 function getId(e) { return document.getElementById(e) } // 给cookie上打个标识,来设置浏览器不支持缓存 function setNotSupportLS() { setCookie("stc_nls", 1, 1) } /** * 读取ls的数据 */ function i(n, r) { var i = ""; // 容错,主要是怕读取出错 try { i = LS[n] || "", // 如果小于99则认为是error,则清空ls版本号 i.length < 99 && (setCookie(r, 0), // 设置页面不可见,然后强制刷新下页面 document.documentElement.style.display = "none", l(), e.onbeforeunload = null, location.reload(!0)) } catch (s) { // 出错时清空版本号 clearLS() } return i } /** * 设置ls数据 */ function setLS(key, t) { try { // 先设置数据到ls // 再读取设置后的内容是否跟源数据相等,如果不相等则清空ls版本,这里主要处理可能ls超大设置失败 LS[key] = t, t !== LS[e] && clearLS() } catch (n) { clearLS() } } /** * 获取cookie */ function o(e) { var n = document.cookie.split("; "); for (var r = 0, i = n.length, s; r < i; r++) { s = n[r].split("="); if (s[0] === e) return s[1] } return "" } /** * 轻量级设置cookie */ function setCookie(key, value, r) { // 默认60天 r = r || 60, // 如果没有值则为-1,也就是清空 value || (r = -1), // 过期时间,单位为天 r = (new Date(+(new Date) + r * 86400000)).toGMTString(); // 生成cookie var i = key + "=" + value + "; path=/; expires=" + r; // 如果是https则加密cookie location.protocol.indexOf("https") > -1 && (i += "; Secure"), // 写入吧,少年 document.cookie = i } /** * 读取id=e的元素内容,写入ls * @param {string} e ls里的key名 * @param {string} t 元素id名 */ function html2ls(e, t) { // 如果元素存在,就获取内容,并去两端空格 var r = getId(t) && getId(t).innerHTML.trim(); setLS(e, r) } /** * 读取ls数据,并生成标签到页面中 */ function ls2html(e, n, r) { var s = i(e, r), o = document.createElement(n); o.innerHTML = s, document.head.appendChild(o) } /** * 清除cookie里的ls版本号 */ function clearLS() { var e = /(?:;)?stc_[^=]*=[^;]*;?/g, n = document.cookie.match(e) || [], r = n.length; while (r) --r, setCookie(n[r].split("=")[0], 0) } /** * 更新版本号,这个很牛b */ function updateVersion(e, t, n) { var r = o(e).split(""), i = !1; // cookie里是以2位版本号紧邻存储,比如: // a文件的一位版本是a,二位版本是b: xxoo=ab // b文件的一位版本是1,二位版本是2: xxoo=ab12 //  // 后端在判断是否有缓存时应该也是这样循环,判断b文件版本对否时循环1,然后判断紧邻的版本是不是2,如果是则认为有缓存,否则认为缓存失败 //  // 这样的好处是cookie值非常的小,因为最多2个版本,比md5要小 // 但由于位数限制,和只能用 数字+字母+部分符号 做为版本 可能文件数量上有些问题,但对于移动端来说应该完全足够 for (var s = 0, a = r.length; s < a; s += 2) // 如果查找到该标识则设置 if (r[s] === t) { r[s + 1] = n, i = !0; break } // 如果找了一圈发现没有标识说明没有设置过cookie则直接添加2位版本号 i || r.push(t, n), // 写入吧 setCookie(e, r.join("")) } var noop = function () {}, LS, d = 0, // 先全部设置空方法 v = e.LS = { html2ls: noop, ls2html: noop, updateVersion: noop }; // 尝试设置ls,如果失败则打上浏览器不支持ls的标识 stc_nls try { LS = localStorage, v.html2ls = html2ls, v.ls2html = f, v.updateVersion = c } catch (m) { setNotSupportLS() }})(this, document)</script><!-- 由于第一次进入页面,则输出html真实代码,并设置到ls里,更新版本号,这里是 !U --><style id="stc_home_next_css"> /*css*/</style><script>LS.html2ls("stc_home_next_css","stc_home_next_css");LS.updateVersion('stc_ls_p_s','!','U')</script><link rel="apple-touch-icon-precomposed"href="/favicon.png"><!-- dns预解析 --><link rel="dns-prefetch"href="//p.ssl.qhimg.com"><link rel="dns-prefetch"href="//s.ssl.qhimg.com"><link rel="dns-prefetch"href="//ps.ssl.qhimg.com"><meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"><meta name="format-detection" content="telephone=no"><meta name=keywords content="360搜索,网页搜索,视频搜索,图片搜索,音乐搜索,新闻搜索,软件搜索,学术搜索"><meta name=description content="360搜索是安全、精准、可信赖的新一代搜索引擎,依托于360母品牌的安全优势,全面拦截各类钓鱼欺诈等恶意网站,提供更放心的搜索服务。 360搜索 so靠谱。"><meta content=always name=referrer><!-- 看下面代码是日志上报方法,并且截获了error报错上报、alert上报,alert上报这个很不错,因为在移动端alert不友好,用上报+统计查看可以知道开发者有没有添加alert,很赞,但我在chrome-pc里测试并没有上报,可能跟环境有关 --><script>(function (e, t, n) { var r = alert, i = encodeURIComponent, // ... e.onerror = function (e, t, n, r, i) { for (var o = 0; o < u.length; ++o) if (s(u[o], e)) return; setTimeout(function () { if (c > 4 || l[e]) return; p({ code: "notice", msg: e }), l[e] = 1, ++c }, 1e3) }, e.alert = function (e) { p({ code: "warning", msg: "alert " + e }), !arguments.length && (e = ""), r(e) }})(this, ENV)</script><!-- 禁用js时隐藏页面,并跳转到极速版本 --><noscript>    <style>body{display:none}</style>    <meta http-equiv=refresh content="0; URL=/s?mode=jisu&noscript=1"></noscript><script>try { // 设置页面样式,应该有版本区分 document.documentElement.className += " w-" + (localStorage.home_w || 0)}catch (e) {}// 速度打点wpo.head = +(new Date) - wpo.start</script><style>html{background:#fff}</style></head><body><header class="i-hd" id=hd>    ...</header><script id="stc_home_next_base">// 这里引用了es6-promise库,可见用了很多promise的api// 这里引用了zepto库和一些常用模块// 这里写了个monitor,主要是日志上报模块</script><script>LS.html2ls("stc_home_next_base","stc_home_next_base");LS.updateVersion('stc_ls_p_s','T','R')</script><script id="stc_common">// 这里是webpack.js// 这里是webpack打包后的一些常用模块,应该是so的公用lib:模板引擎、 能用滚动事件、解析url参数、webp图片适配(切图)、图片延迟加载(跟dom有耦合)、节流、https代理(但我试了几个图片发现不管用,应该做了域名白名单或者我姿势不对)// 这里是基于webpack生成的MSO.observer,看代码应该是整个页面的事件驱动,应该有些固定的勾子,比如scroll、show之类,好处是事件统一接管,提供页面hook// 下面有一个牛b的东西登场:window._loader,看意思是个加载器,但她不只是加载器,在代码大概意思是:// 在使用时 _loade.use(uri),然后会首先判断该uri模块有没有被执行:// 如果执行过:则直接执行回调// 如果未执行过:// 读取ls里是否有该uri:// 有:// 判断版本:// 匹配:读取ls并执行回调// 不匹配:执行加载远程操作// 没有:// 直接加载文件,文件的内容类似jsonp,加载成功后会执行回调,并把文件md5+内容写入ls以方便后续使用// 再往下就是些逻辑代码不说了</script><script>LS.html2ls("stc_common","stc_common");LS.updateVersion('stc_ls_p_s','(','(')</script></body></html>
로그인 후 복사

总结

开发模式

看代码应该是使用的 es6开发,使用 webpack来打包成浏览器端可运行版本,这样开发效果很高,但感觉也并没有使用 es6的全部特性,因为全部特性需要 runtime环境,而这个环境的 shim不小,我看有 promise-shim,感觉应该只用了部分功能,然后转换。但在一定的程度上也可以提高开发效率~

localStorage的应用

使用 localStorage来缓存静态文件的手法很常见,但 so的方式很新颖:

  1. cookie里使用2位版本号存放,这样很能减少 cookie的体积,由其是在流量很大的站
  2. 常用模块也使用 localStorage来存在,如果不存在则异步请求,这样也很省流量呢,比如iscroll、城市code数据,你懂的~

之前写的一个: 设计localStorage自动更新

事件管理

整个页面统一由 MSO.observer接管,公用事件统一 trigger(在这里叫 publish),我相信 so内部肯定有这方面的文档,并且有公用事件详细的说明~

比如页面加载完成有 load事件、搜索框聚焦时有 search:focus事件,这样的事件 hook可以很好的使不同模块之间的通信和判断

其他的一些

比如容错做的很好,不至于你关了 cookie或者 ls就报错,还有使用了 webp,并且我看上面有 window.ENV变量,应该是 server端判断了ua信息输出的

当然还有很多有特我的发现~

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

& lt; Progress & Gt의 목적은 무엇입니까? 요소? & lt; Progress & Gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:34 PM

이 기사는 HTML & lt; Progress & Gt에 대해 설명합니다. 요소, 그 목적, 스타일 및 & lt; meter & gt의 차이; 요소. 주요 초점은 & lt; progress & gt; 작업 완료 및 & lt; meter & gt; Stati의 경우

& lt; datalist & gt의 목적은 무엇입니까? 요소? & lt; datalist & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:33 PM

이 기사는 HTML & LT; Datalist & GT에 대해 논의합니다. 자동 완성 제안을 제공하고, 사용자 경험을 향상시키고, 오류를 줄임으로써 양식을 향상시키는 요소. 문자 수 : 159

& lt; meter & gt의 목적은 무엇입니까? 요소? & lt; meter & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:35 PM

이 기사는 HTML & lt; meter & gt에 대해 설명합니다. 범위 내에 스칼라 또는 분수 값을 표시하는 데 사용되는 요소 및 웹 개발의 일반적인 응용 프로그램. & lt; meter & gt; & lt; Progress & Gt; 그리고 Ex

HTML은 초보자를 위해 쉽게 배우나요? HTML은 초보자를 위해 쉽게 배우나요? Apr 07, 2025 am 12:11 AM

HTML은 간단하고 배우기 쉽고 결과를 빠르게 볼 수 있기 때문에 초보자에게 적합합니다. 1) HTML의 학습 곡선은 매끄럽고 시작하기 쉽습니다. 2) 기본 태그를 마스터하여 웹 페이지를 만들기 시작하십시오. 3) 유연성이 높고 CSS 및 JavaScript와 함께 사용할 수 있습니다. 4) 풍부한 학습 리소스와 현대 도구는 학습 과정을 지원합니다.

뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? 뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? Mar 20, 2025 pm 05:56 PM

이 기사는 모바일 장치의 반응 형 웹 디자인에 필수적인 Viewport Meta Tag에 대해 설명합니다. 적절한 사용이 최적의 컨텐츠 스케일링 및 사용자 상호 작용을 보장하는 방법을 설명하는 반면, 오용은 설계 및 접근성 문제로 이어질 수 있습니다.

& lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? & lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? Mar 20, 2025 pm 06:05 PM

이 기사는 & lt; iframe & gt; 외부 컨텐츠를 웹 페이지, 공통 용도, 보안 위험 및 객체 태그 및 API와 같은 대안을 포함시키는 태그의 목적.

HTML, CSS 및 JavaScript의 역할 : 핵심 책임 HTML, CSS 및 JavaScript의 역할 : 핵심 책임 Apr 08, 2025 pm 07:05 PM

HTML은 웹 구조를 정의하고 CSS는 스타일과 레이아웃을 담당하며 JavaScript는 동적 상호 작용을 제공합니다. 세 사람은 웹 개발에서 의무를 수행하고 화려한 웹 사이트를 공동으로 구축합니다.

HTML의 시작 태그의 예는 무엇입니까? HTML의 시작 태그의 예는 무엇입니까? Apr 06, 2025 am 12:04 AM

anexampleStartingtaginhtmlis, whithbeginsaparagraph.startingtagsareessentialinhtmlastheyinitiate rements, definetheirtypes, andarecrucialforstructurituringwebpages 및 smanstlingthedom.

See all articles