顯示具有 網頁設計 標籤的文章。 顯示所有文章
顯示具有 網頁設計 標籤的文章。 顯示所有文章

網站開發的前端技術變化

 



2021/10/9 整理

現在前端已經進入了 MVVM 時代,但 jQuery 並不會退出歷史舞台,即使沒人用 XP、Win7 操作系統,即使所有人都用 Chrome 也不會。jQuery 手工操作已經存在的 DOM,操作比較精細,性能好但開發效率低,瀏覽器兼容較好,各個門戶主要還是用 jQuery。


MVVM 解決的是開發效率問題,構建複雜表單比較順手,大大降低了手工操作 DOM 的代碼量,適合內部應用,管理後台,但 MVVM 不是萬能的,缺點是

1. 要實現 DATA 變化的雙向綁定,一般瀏覽器兼容差

2. DOM 動態生成無法 SEO,搜索引擎搜不到

3. 通過數據操作 DOM 實質上不夠精細,有一點性能上的損耗


jQuery 解決的是遠古時代的瀏覽器兼容問題,將 DOM 操作做了一層兼容性封裝,但其用法本質上與直接使用原生 JS 接口沒有什麼不同。

1. 原生操作 DOM 不可能消失,雖然已經有了 document.querySelectorAll(selector),但有沒有覺得還是 $(selector) 更方便?雖然有了 element.addEventListener(event, handler) 但 $(select).on(event, handler) 是不是更簡潔?

2. jQuery 有一個強大的前端生態

畢竟流行了十幾年,目前很多複雜前端組件、框架都基於 jQuery,比如說編輯器,日期選擇器,自動提示等,你可以用 MVVM 來重寫,但動態渲染 DOM 與穩定性 DOM 有先天的性能差距,越複雜的控件,MVVM 的性能損失越明顯。

而且基於 jQuery 相當於基於原生 JavaScript,jQuery 可以視為原生 API 的一層封裝,以後沒有瀏覽器兼容問題了,自己實現一個 jQuery 適配器即可,比如 zepto,所有基於 jQuery 的組件可以直接用。







JavaScript 和 jQuery 混用

JavaScript window.onload 和 jQuery $(document).ready() 的差異

在撰寫頁面的 JavaScript 或 jQuery 時,通常會利用 window.onload 事件或 $(document).ready() 事件來確保 DOM 完全載入,不過兩者仍有以下差異。


window.onload 會等網頁的全部內容,包括圖片,CSS及 <iframe> 等外部內容都載入後才會觸發,但 $(document).ready() 在 Document Object Model (DOM) 載入後就會觸發,所以順序上$(document).ready() 會比 window.onload 先執行。


window.onload 是 JavaScript 的原生事件,而 $(document).ready() 是 jQuery 的事件(其實是透過監聽 JavaScript 的 DOMContentLoaded 事件來實現)。


window.onload 的用法如下:

window.onload = function() {

  // console.log("window loaded")

};


$(document).ready() 的用法如下:

$(document).ready(function() {

  console.log("document ready");

});

// 也可簡寫成

$(function() {

  console.log("document ready");

});



jQuery 轉為 JavaScript: var jsObject=$("#id").get(0);

JavaScript 轉為 jQuery: var $object=$(document.getElementById("id"));



JavaScript 呼叫 jQuery 方法:

function getResult(){

    $().getFuc();

};

$(function(){

    $.fn.getFuc=function(){

        alert("1111111111111");

    }

});


 jQuery 呼叫 JavaScript 方法:

$("#button3").click(function () {

        getFuc();

    });

function getFuc(){

       alert("111111");

}



在 HTML 中使用 onclick 方法與 jQuery 的事件監聽有何差異 (JS 亦能實現) ?

onclick 通常是在滿足以下條件時才優先於 .click 的方法:

1. 只有一個事件要為 click 事件註冊
2. 擔心移動性能/電池壽命

jQuery 以犧牲性能為代價來綁定所有事件。

如果我們談論性能,在任何情況下直接使用總是更快。


但倡導事件監聽的理由是 JavaScript 和 佈局(HTML) 應該分開
提倡者認為任何這些事件創建 evenHandler 是更好,一個事件可以捕獲多個項目,而不是為每個事件創建單獨的腳本



防禦利用 iframe 的站點劫持攻擊

https://paper.seebug.org/papers/Archive/drops2/Clickjacking%E7%AE%80%E5%8D%95%E4%BB%8B%E7%BB%8D.html



各種防禦與破解的方法整理


推荐的防御方法:


一、X-FRAME-OPTIONS

X-FRAME-OPTIONS是微软提出的一个http头,专门用来防御利用iframe嵌套的点击劫持攻击。

并且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支持。

这个头有三个值:

DENY               // 拒绝任何域加载

SAMEORIGIN         // 允许同源域下加载

ALLOW-FROM         // 可以定义允许frame加载的页面地址

php中设置示例:

header ( "X-FRAME-OPTIONS:DENY");

二、目前最好的 JavaScript 的防御方案为:

<head>
<style> body { display : none;} </style>
</head>
<body>
<script>
if (self == top) {
    var theBody = document.getElementsByTagName('body')[0];
    theBody.style.display = "block";
} else {
    top.location = self.location;
}
</script>




0x00 相关背景介绍

Clickjacking(点击劫持)是由互联网安全专家罗伯特·汉森和耶利米·格劳斯曼在2008年首创的。

是一种视觉欺骗手段,在web端就是iframe嵌套一个透明不可见的页面,让用户在不知情的情况下,点击攻击者想要欺骗用户点击的位置。

由于点击劫持的出现,便出现了反frame嵌套的方式,因为点击劫持需要iframe嵌套页面来攻击。

下面代码是最常见的防止frame嵌套的例子:

if(top.location!=location)
    top.location=self.location;

事实上,这种代码很容易被绕过,在后文中讨论。

0x01 防御的几种方式

防止frame嵌套的js使用代码由高到低比例:

if (top != self)
if (top.location != self.location)
if (top.location != location)
if (parent.frames.length > 0)
if (window != top)
if (window.top !== window.self)
if (window.self != window.top)
if (parent && parent != window)
if (parent && parent.frames && parent.frames.length>0)
if((self.parent&&!(self.parent===self))&&(self.parent.frames.length!=0))

检测到后的处理方案:

top.location = self.location
top.location.href = document.location.href
top.location.href = self.location.href
top.location.replace(self.location)
top.location.href = window.location.href
top.location.replace(document.location)
top.location.href = window.location.href
top.location.href = "URL"
document.write('')
top.location = location
top.location.replace(document.location)
top.location.replace('URL')
top.location.href = document.location
top.location.replace(window.location.href)
top.location.href = location.href
self.parent.location = document.location
parent.location.href = self.document.location
top.location.href = self.location
top.location = window.location
top.location.replace(window.location.pathname)
window.top.location = window.self.location
setTimeout(function(){document.body.innerHTML='';},1);
window.self.onload = function(evt){document.body.innerHTML='';}
var url = window.location.href; top.location.replace(url)

0x02 绕过的几种方式

对于使用parent.location来防御的可以使用多层嵌套的方式绕过。

一、例如防御代码为:

if(top.location!=self.location){
     parent.location = self.location;
}

建立两个页面:

1.html代码为:

<iframe src="2.html">

2.html代码为:

<iframe src="http://www.victim.com">

访问1.html之后可以看到页面并无跳转等动作。

http://static.wooyun.org/20141017/2014101711515250154.png

二、onBeforeUnload函数的利用:

onBeforeUnload的介绍以及各种浏览器的支持情况请见:

http://w3help.org/zh-cn/causes/BX2047

如下的防御代码:

if(top != self) top.location.replace(location);

新建立页面,代码如下:

<script>
var framekiller = true;
window.onbeforeunload = function() { if(framekiller) { return
"Write something here to keep people stay!";} };
</script>
<iframe src="http://www.victim.com/">

打开页面显示如下:

http://static.wooyun.org/20141017/2014101711515274922.png

欺骗用户点击留在此页后显示:

http://static.wooyun.org/20141017/2014101711515228109.png

三、XSS filter的利用

IE8以上以及Chrome浏览器都有XSS筛选器,这些可以用来对付防御frame嵌套的代码。

防御代码如下:

if(top!=self){
    top.location=self.location;
}

新建立页面,代码如下:

<iframe src="http://www.victim.com/?<script>">

访问后页面显示:

http://static.wooyun.org/20141017/2014101711515211018.png

IE的xss筛选器自动拦截了跳转。

斯坦福的文章里写了Chrome也会出现这种情况,并给出了攻击代码:

<iframe src=http://www.victim.com/?v=if(top+!%3D+self)+%7B+top.location%3Dself.location%3B+%7D">

但是测试发现,新版的Chrome并不会拦截了,会直接跳转过去。

如果跟的参数中有变量在页面中显示的,会把变量过滤一遍再输出,但不会阻止跳转。

四、Referer检查的问题

有一些站点允许自己的域名嵌套自己,禁止外站对自己的嵌套。

通常是用document.referer来检测来源是否为自己的域名。

if(top.location!=location){
    if(document.referrer && document.referrer.indexOf("aaa.com")==1)
    {
        top.location.replace(document.location.href);
    }
}

判断字符串中是否含有本域名是常见的错误用法,利用二级域名的方式便可绕过,如:

http://aaa.com.bbb.com

注:从https域下post数据到http域的时候,浏览器不带Referer。

IE有个属性可以设置security为restricted可以禁止iframe里执行js脚本,但是要达到点击劫持的效果,必须要能够执行js所以很鸡肋。

代码如下:

<iframe src="http://www.victim.com/iframe.html" security="restricted"></iframe>

重点是手机站点,很多主站做的很不错,但是手机站点没有做任何防护,很容易造成点击劫持。

五、location劫持

在IE浏览器中,如果能够在防御代码的前面可以插入form表单的话,可以利用form表单对location进行劫持。

<form name=self location="javascript:alert(1)"></form>
<script>
if(top!=self){
   top.location=self.location
}
</script>

用iframe嵌套此代码,可以看到没有跳转,执行了alert(1)。



Progressive Web App 會是未來趨勢嗎?

https://blog.techbridge.cc/2016/07/23/progressive-web-app/


何謂 Progressive Web App (PWA)

先講結論,Progressive Web App 是希望能夠讓 Web application 盡可能的在各種環境(網路環境、手機作業系統等)下都能順暢且不減功能性的運作,並讓你的 Web App 可以:

  1. 直接被使用者安裝到桌面
  2. offline 使用
  3. 擁有推播功能
  4. 開啟時看不到 URL Bar(類 Native app 的使用經驗)
  5. 開啟時有 Splash Screen

而要做到這些事情,整個 PWA 的設計要點就會包含以下特性:

  • Progressive - 漸進增強:在越完善的環境下,能執行更加完整的服務,若環境不許可,能夠優雅降級,運行最基本的功能。

  • Responsive - 響應式介面:能夠在各種螢幕尺寸下顯示、能夠因應多種輸入方式與設備回饋(震動、音頻等)。

  • App-like - 類原生程式的操作模式與使用者介面:採用原生平台(Native App)的 Style 與資料更新方式(利用 service worker 存取快取資源)。

  • Fresh - 持續更新:使用 Service worker API 來自動更新應用程式(無需透過 App store, Google Play 等)。

  • Safe - 應全面採用 HTTPS 提供最基本的安全防護。

  • Discoverable - 透過設置 manifest 檔案,一樣能進行 SEO 優化,讓搜尋引擎找得到你的 APP。

  • Re-engageable - 透過推播,能主動與使用者互動。

  • Installable - 可安裝:透過 Add To Home 等方式,將 Web App 放在手機桌面,並且能在應用程式中單獨列出與切換,就像一般的 App 一樣,但完全不用透過應用程式商店下載。

  • Linkable - 透過 URL 可以隨時分享你的 App。

上面是官網所列出的,而紅色是我認為較為重點的特徵,而在這些重點特徵下,最大要點就是 Service worker。有了 Service worker 的幫助,你可以實作出離線可用的 Web App,讓 User 操作起來有更佳的使用體驗。

JavaScript: ECMAScript 相容性


腳本引擎參考應用程式相容性[11]
ES5[12]ES6[13]ES7[14]較新(2016+)[14][15]
ChakraMicrosoft Edge 18100%96%100%58%
SpiderMonkeyFirefox 63100%98%100%78%
Chrome V8Google Chrome 70、Opera 57100%98%100%100%
JavaScriptCore(Nitro)Safari 1299%99%100%90%


Google 的 URL 相關參數


https://developers.google.com/custom-search/docs/xml_results?hl=en&csw=1

https://sites.google.com/site/tomihasa/google-language-codes

Google Maps嵌入參數:https://jax-work-archive.blogspot.com/2011/07/google-maps.html



 the tbm URL parameter appears to indicate the filter used. For example:

Applications: tbm=app
Blogs: tbm=blg
Books: tbm=bks
Discussions: tbm=dsc
Images: tbm=isch
News: tbm=nws
Patents: tbm=pts
Places: tbm=plcs
Recipes: tbm=rcp
Shopping: tbm=shop
Video: tbm=vid



gl
Description
Optional. The gl parameter value is a two-letter country code. For WebSearch results, the glparameter boosts search results whose country of origin matches the parameter value. See the Country Codes section for a list of valid values.
Specifying a gl parameter value in WebSearch requests should improve the relevance of results. This is particularly true for international customers and, even more specifically, for customers in English-speaking countries other than the United States.
Examples
This request boosts documents written in the United Kingdom in WebSearch results:
q=pizza&gl=uk


hl
Description
Optional. The hl parameter specifies the interface language (host language) of your user interface. To improve the performance and the quality of your search results, you are strongly encouraged to set this parameter explicitly.
See the Interface Languages section of Internationalizing Queries and Results Presentation for more information and Supported Interface Languages for a list of supported languages.
Examples
This request targets ads for wine in French. (Vin is the French term for wine.)
q=vin&ip=10.10.10.10&ad=w5&hl=fr




CSS Sprite 與 RWD 的整合:縮放大小

http://www.manongjc.com/article/26907.html

transform:scale( x )

语法为 transform: scale(x,y). 同时有 scaleX, scaleY 专门的 x, y 方向的控制,
例如 transform: scale(0.5) 缩小为原来的一半。
scale 并不支持百分比和 normal关键字,只能是数值。而且还能是负数。

zoom:x

zoom 支持百分比和 normal 关键字,不支持負數, zoom:0.5 也是缩小为原来的一半。

zoom:normal | <number> | <percentage>

在文档中,zoom 加在任意一个元素上都会引起一整个页面的重新渲染,而 scale 只是在当前的元素上重绘。

当你给一个 div 固定宽高时,scale 变化的时候,其原本的宽高还是不变的,只不过里面的元素缩小了而已,因此,就没有 layout 的重计算。

但是 zoom 則會進行 layout 的重计算。

HTML iframe 框架語法與其使用限制與缺點


被放進框架的內容網頁不見得能夠在 手機 等行動裝置上 正常運作,相容性很混亂

https://blog.csdn.net/Abraham_bug/article/details/80053210

無法滾動、解決滾動同時要防止框架外的移動等等衝突問題


HTML iframe 框架語法 => HTML5 改為使用 CSS 設定
https://www.w3schools.com/tags/tag_iframe.asp

iframe 連結另外開啟新視窗或在原本網頁開啟
http://www.wibibi.com/info.php?tid=374

深入了解 /iframe有那些缺點/ Iframe傳值問題
https://medium.com/@small2883/iframe%E4%BB%8B%E7%B4%B9-%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3-iframe%E6%9C%89%E9%82%A3%E4%BA%9B%E7%BC%BA%E9%BB%9E-iframe%E5%82%B3%E5%80%BC%E5%95%8F%E9%A1%8C-579e6c113436

iframe這個詞是inline frame的縮寫。

iframe屬性:

1.frameborder:是否顯示邊框,1(yes),0(no)
2.height:height屬性指定了iframe的像素高度,建議使用css設置。
3.width:width屬性指定了iframe的像素寬度,建議使用css設置。
4.name:iframe的名稱,window.frames[name]時專用的屬性。
5.scrolling:iframe是否滾動。yes,no,auto。
6.src:iframe的網址。
7.sandbox:控制iframe內的權限(html5新功能):http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/?redirect_from_locale=zhhttp://msdn.microsoft.com/en-us/hh563496.aspx

為什麼前端盡量少用iframe? iframe有哪些缺點:

1.iframe会阻塞主頁面的Onload事件;
2.搜索引擎的檢索程序無法解讀這種頁面,不利於SEO;
3.iframe和主頁面共享連接池,而瀏覽器對同域的連接有限制,所以会影響頁面的並行加載。
4.因为iframe等于打開一个新的網頁,所有的JS/CSS全部加載一遍,内存会*2
5.是否同域的問題

我们通常使用iframe最基本的特性,就是能自由操作iframe和父框架的内容(DOM)。
但前提條件是同域,如果跨域頂多只能實現頁面跳轉window.location.href。

同域時,父頁面可以对子頁面進行改寫,反之亦然。
不同域,父頁面没有權限改動子頁面,但可以實現頁面的跳轉。

如果需要使用 iframe,最好是通过 javascript 動態给 iframe 添加 src 屬性值,这样可以避開一些 iframe 的缺點:

https://stackoverflow.com/questions/6000987/dynamically-set-iframe-src

跨域傳值,方法之一是使用
window.frames[0].postMessage($txt_val, ‘*’); 傳值
window.addEventListener(“message”, receiveMessage);取值
可參考
https://dotblogs.com.tw/daniel/2017/11/25/225511
https://www.cnblogs.com/dolphinX/p/3464056.html
https://blog.csdn.net/kenhins/article/details/50789125

jQuery 的動畫函式

https://www.darkthread.net/jQuery/Tutorial09/default.htm

【常用特效函數】

show() 將隱藏的元素立刻顯示出來,若元素已可見則沒有變化。
show(speed[, callback]) 在speed指定的時間內(即animate的duration,可以是"slow"、"normal"、"fast"或是數字代表微秒數,以下將不再重覆說明),將width, height由0變到原有尺寸,透明度也明完全透明變成不透明。callback即前述的complete函數,在特效結束後呼叫(稍後在其他函數中用到時便不再重覆說明)。
hide() 將顯示的元素立刻隱藏,已隱藏者不受影響。
hide(speed[, callback]) 在speed指定的時間內將width, height, opacity縮為0。
toggle() 切換元素的顯示狀態,將可見者隱藏,隱藏者顯示出來。
toggle(switch) switch為一Boolean變數,true時顯示,false時隱藏。
slideDown(speed[, callback]) 在speed指定時間內將height由0遞增至原有高度,形成向下拉開的視覺效果。
slideUp(speed[, callback]) 在speed指定時間內將height由原有高度遞減至0,形成向下收合的視覺效果。
slideToggle(speed[, callback) 切換元素的顯示狀態,將可見者隱藏,隱藏者顯示出來,但過程使用slideDown, slideUp效果。
fadeIn(speed[, callback]) 在speed指定時間內將opacity由透明逐漸變成不透明,形成漸漸浮現的視覺效果。
fadeOut(speed[, callback]) 在speed指定時間內將opacity由不透明逐漸變成透明,形成慢慢消失的視覺效果。
fadeTo(speed, opacity[, callback)  在speed指定時間內將opacity逐漸變成指定的透明度。

Access-Control-Allow-Origin 跨域訪問相關議題

理解 Ajax 與跨來源請求:https://blog.techbridge.cc/2017/05/20/api-ajax-cors-and-jsonp/

原來 CORS 沒有我想像中的簡單:https://blog.techbridge.cc/2018/08/18/cors-issue/

HTML2Canvas:用Javascript來做螢幕截圖,仍然會受到 跨域訪問 限制
http://www.ladesign.tw/paper/info/jquery_html2canvas_download



ajax 设置Access-Control-Allow-Origin实现跨域访问
https://blog.csdn.net/fdipzone/article/details/46390573

摘要:
ajax跨域访问是一个老问题了,解决方法很多,比较常用的是JSONP方法,JSONP方法是一种非官方方法,而且这种方法只支持GET方式,不如POST方式安全。

如果跨域使用POST方式,可以使用创建一个隐藏的iframe来实现,与ajax上传图片原理一样,但这样会比较麻烦。

ps. 如何創建一個隱藏的 iframe:http://21st.each1.net/2018/07/csrf-cross-site-request-forgery.html

因此,通过设置Access-Control-Allow-Origin来实现跨域访问比较简单。

例如:客户端的域名是www.client.com,而请求的域名是www.server.com

如果直接使用ajax访问,会有错误

在被请求的Response header中加入

// 指定允许其他域名访问
header('Access-Control-Allow-Origin:*');
// 响应类型
header('Access-Control-Allow-Methods:POST');
// 响应头设置
header('Access-Control-Allow-Headers:x-requested-with,content-type');
就可以实现ajax POST跨域访问了。

實現的代碼摘要如下:

client.html 路径:http://www.client.com/client.html

<script type="text/javascript">
    $.post("http://www.server.com/server.php",{name:"fdipzone",gender:"male"})
      .done(function(data){
        document.getElementById("show").innerHTML = data.name + ' ' + data.gender;
      });
</script>

server.php 路径:http://www.server.com/server.php

<?php
$ret = array(
    'name' => isset($_POST['name'])? $_POST['name'] : '',
    'gender' => isset($_POST['gender'])? $_POST['gender'] : ''
);

header('content-type:application:json;charset=utf8');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST');
header('Access-Control-Allow-Headers:x-requested-with,content-type');

echo json_encode($ret);
?>

Access-Control-Allow-Origin:* 表示允许任何域名跨域访问
如果需要指定某域名才允许跨域访问,只需把Access-Control-Allow-Origin:*改为Access-Control-Allow-Origin:允许的域名

例如:header('Access-Control-Allow-Origin:http://www.client.com');

如果需要设置多个域名允许访问,这里需要用php处理一下

例如允许 www.client.com 与 www.client2.com 可以跨域访问

server.php 修改为

<?php
$ret = array(
    'name' => isset($_POST['name'])? $_POST['name'] : '',
    'gender' => isset($_POST['gender'])? $_POST['gender'] : ''
);

header('content-type:application:json;charset=utf8');

$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';

$allow_origin = array(
    'http://www.client.com',
    'http://www.client2.com'
);

if(in_array($origin, $allow_origin)){
    header('Access-Control-Allow-Origin:'.$origin);
    header('Access-Control-Allow-Methods:POST');
    header('Access-Control-Allow-Headers:x-requested-with,content-type');
}

echo json_encode($ret);
?>




使用 javascript 動態更改 CSS 的各種方式

https://www.jianshu.com/p/0260cddff86a


在很多情况下,都需要对网页上元素的样式进行动态的修改。在JavaScript中提供几种方式动态的修改样式,下面将介绍方法的使用、效果、以及缺陷。
1、使用obj.className来修改样式表的类名。
2、使用obj.style.cssTest来修改嵌入式的css。
3、使用obj.className来修改样式表的类名。
4、使用更改外联的css文件,从而改变元素的css

下面是一段html代码和css代码用来解释上面方法的区别的。

CSS

.style1{margin:10px auto ;background-color:#9999FF; display:block;color:White; border:1px solid white; padding:10px 25px; font-size:18px; }

.style1:hover{ background-color:#66B3FF; cursor:pointer;}

.style2{margin:10px auto ;background-color:gray; display:block;color:black; border:1px solid white; padding:10px 25px; font-size:18px; }

.style2:hover{ background-color:black; color:White; cursor:pointer}

HTML

 <div>
        <input id="btnB" type="button" name="btnLogin" value="登录" class="style1" />
        <div id="tool">
            <input type="button" value="【obj.style.className】更改样式" onclick="changeBackgroundColor()"/>
            <input type="button" value="【obj.style.cssText】更改样式" onclick="changeFontSize()" />
            <input type="button" value="【obj.className】更改样式" onclick="addRadius()" />
            <input type="button" value="更改外联css样式" onclick="recover()" />
        </div>
    </div>


一、使用obj.className来修改样式表的类名

从下面的代码可以看出ob.style.cssTest是如何来btnB的样式的。

 function changeStyle1() {
            var obj = document.getElementById("btnB");
            obj.style.backgroundColor= "black";

  }

该段代码修改btB的文字的颜色,在浏览器中打开调试工具,可以发现btB标签中多了一个属性【style="background-color:black"】,从而改变btB的样式。

缺陷:
在修改btB的背景色之后用鼠标放到btB上可以发现,btB的伪类hover里面的css根本不起作用。原来是当你修改了这个这样样式之后。在btB的内联样式中多了background-color属性了,在css的应用中也是有级别的,嵌入式>内联式>外联式。而btB的hove伪类的background-color样式写在内联式中,所以嵌入式的background-color覆盖了伪类中,这就使得鼠标放入btB上感觉不到背景颜色的变化。


二、使用obj.style.cssTest来修改嵌入式的css

直接上JavaScript代码:

 function changeStyle2() {
            var obj = document.getElementById("btnB");
            obj.style.cssText = "background-color:black; display:block;color:White;

}

该段代码和【一】中的效果是一样的,缺陷也是一样。


三、使用obj.className来修改样式表的类名

使用代码来修改btB引用样式的类名,如下段代码:

  function changeStyle3() {
            var obj = document.getElementById("btnB");
            //obj.className = "style2";
            obj.setAttribute("class", "style2");
    }

通过更改btB的css的类名的方式来更改样式,更改样式类名有两种方式。1、obj.className = "style2";  2、 obj.setAttribute("class", "style2");都是一样的效果。

用这种方式来修改css比上面的效果要好很多。

四、使用更改外联的css文件,从而改变元素的css

通过更改外联的css文件引用从而来更改btB的样式,操作很简单。代码如下:

首先得引用外联的css文件,代码如下:

<link href="css1.css" rel="stylesheet" type="text/css"  id="css"/>

function changeStyle4() {
            var obj = document.getElementById("css");
            obj.setAttribute("href","css2.css");
   }

这样也能方便的更改btB的样式,个人觉得这种方式是最好用的。是实现整体页面换肤的最佳方案。

CSS Fonts - 系統內建字體的相關設定

詳閱 https://www.w3schools.com/css/css_font.asp




文章的發布時間與更新時間

https://www.seoseo.com.tw/article_detail_275.html
https://www.biaodianfu.com/google-serp-date.html

文章類型的網頁應該要有『相關時間』,並放在文章的最上面;
更新日期放在發布日期之前。

要時常更新文章內容:
1. 部份的更新,例如:句子加長、添加新的關鍵字在文章中、標題調整、錯字更正
2. 調整更新日期,讓文章出現在最頂端,也就是網站中最新的一篇文章
3. 更新文章的 title、description 等 Metadata
4. 當作新文章去進行推廣,例如:利用電子報、社群去做宣傳

Alert、confirm 及 prompt 對話盒

http://www.takka.com.hk/jstutor/ch3/ch3.htm

在實務應用上,Javascript 原生的對話盒外貌與 OS系統的警告視窗太過相似,會帶給網站訪客/用戶 心理上不好的感受,所以僅可參考其邏輯流程,並重新設計與自身網站美術設計渾然一體的動態 Dialog 與 UX。

網站的效能優化

作為通用的原則,雅虎的工程師團隊曾經給出過35個最佳實踐,這個列表請參考
Best Practices for Speeding Up Your Web Site
https://developer.yahoo.com/performance/rules.html

陳希章@中國
https://www.cnblogs.com/chenxizhang/archive/2013/05/20/3088196.html

WebSocket

詳閱 http://muki.tw/tech/websocket-simple-introduce-and-use/


以下為頁庫存檔:

什麼是 WebSocket?

實作之前,免不俗的要跟大家分享一下 WebSocket 到底是什麼,以下取自 wiki 百科的解釋:
WebSocket 是 HTML5 開始提供的一種瀏覽器與伺服器間進行全雙工通訊的網路技術。WebSocket 通訊協定於 2011 年被 IETF 定為標準 RFC 6455,WebSocketAPI 被 W3C 定為標準。
在 WebSocket API 中,瀏覽器和伺服器只需要要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。
@ WebSocket / wikipedia
簡單來說,就是有 Client & Server 兩端透過 WebSocket 互相傳遞與接收資料,並且即時顯示在頁面上。

WebSocket 語法說明

WebSocket 的大架構其實很簡單又直覺,他也有一些既有的事件,我們只要知道確定哪些事件發生時,該做什麼事情?把這些事情塞到對應的事件即可。
在 WebSocket 官方網站也有提供測試的頁面以及語法結構,以下就使用他提供的 Example 來跟大家說明:
JavaScript
<!DOCTYPE html>
    <meta charset="utf-8" />
    <title>WebSocket Test</title>
    <script language="javascript" type="text/javascript">
        var wsUri = "ws://echo.websocket.org/";
        var output;
            function init() {
                output = document.getElementById("output");
                testWebSocket();
            }
            function testWebSocket() {
                websocket = new WebSocket(wsUri);
                websocket.onopen = function(evt) { 
                    onOpen(evt)
                    };
                websocket.onclose = function(evt) {
                    onClose(evt)
                };
                websocket.onmessage = function(evt) {
                    onMessage(evt)
                };
                websocket.onerror = function(evt) {
                    onError(evt)
                };
            }
            function onOpen(evt) {
                writeToScreen("CONNECTED"); 
                doSend("WebSocket rocks"); 
            }  
            function onClose(evt) { 
                writeToScreen("DISCONNECTED"); 
            }  
            function onMessage(evt) { 
                writeToScreen('RESPONSE: ' + evt.data+''); 
                websocket.close(); 
            }  
            function onError(evt) { 
                writeToScreen('ERROR: ' + evt.data); 
            }  
            function doSend(message) { 
                writeToScreen("SENT: " + message);
                websocket.send(message); 
            }  
            function writeToScreen(message) { 
                var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); 
            }  
            window.addEventListener("load", init, false);  
        </script>  
        <h2>WebSocket Test</h2>  
        <div id="output"></div>  
WebSocket 已經建立好許多 function ,我們可以直接用他的 function,當然也不一定要全部 function 都用到,或是可以做點小修改,像我主管給我的範本就跟官網提供的有一點點不一樣(但基本上的呼叫是大同小異的)
  • 第 5 行:老實說我覺得所有語法中最重要的就是第 5 行的 var wsUri = "ws://echo.websocket.org/";,因為如果一開始沒有把傳輸的網址寫正確,之後的效果根本也跑不出來。記得要把 http:// 改成 ws://。
  • 第 13 行:websocket.onopen這個事件是用來判斷前面的 wsUri 是否有順利抓到,如果有抓到表示 onopen,可以利用console.log或是alert做個標記:console.log("連線成功");
  • 第 16 行:跟第 13 行的事件對照就很清楚的知道,websocket.onclose是用來表示當連線中斷時,會出現什麼訊息或事件。
  • 第 19 行:wescoket.onmessage是整個 WebSocket 的重頭戲,連線後,我們就可以在onmessage裏面寫上任何想要傳輸的事件內容。
  • 第 22 行:而對應 19 行的wescoket.onmessage,wescoket.onerror是用來判斷連線或事件的正確與否,如果有出現了任何錯誤,就會觸發onerror事件,所以我們可以在這邊進行除錯。
WebSocket 主要就是這四個事件,所以其實不難。那要怎麼利用 jQuery 結合 WebSocket 做出想要的功能呢?我們做法通常是將 jQuery 的主要 function 跟 WebSocket 拆開來,簡單架構參考如下:
Bash
主資料夾
├ effect.js
├ websocket.client.js
├ websocket.master.js
├ websocket.client.html
├ websocket.master.html
由此可看出,將主要的功能寫在 effect.js 裏頭, client.js(html) 與 master.js(html) 分別用來表示兩個不同網頁,他們可以有不同的功能,也可以互相傳收資料 。

利用 JSON 傳遞 WebSocket

步驟一

在 effect.js 先將所有要顯示的資料存到變數中:
JavaScript
var _name = $("#name").val();
var _company = $("#company").val();

步驟二

利用 JSON 將資料送給 WebSocket:
JavaScript
websocket.send(JSON.stringify({
    'username': _name,
    'company': _company,
}));

步驟三

在 client.js 將收到的資料存到變數中並調用:(請寫在websocket.onmessage事件裡。)
JavaScript
//設置一個變數 data, 將剛剛 JSON 的資料存入
var data = $.parseJSON(e.data);

//以下可調用該 data
username = data.username
company = data.company
以上簡單幾行,就可以完成 WebSocket 的基本功能囉 🙂

在兩個不同的網頁中 (master.html, client.html) 互傳資料

假使我們希望在 master.html 做了一個動作 (比如說點選特定的分頁時),client.html 就會秀出一個 DIV。那麼要怎麼做出這功能呢?
我們在切換 TAB 的時候,通常網址列後面都會多一個「#+英數字」作為標記,而我們可以利用這個標記來識別現在是切換到第幾個分頁,然後針對指定的分頁,在 client.html 顯示一個 DIV。

步驟一

先在 master.js 設定一個事件,將 #(hash) 給擷取出來:
JavaScript
$(window).keyup('hashchange', function() {
    var tab= location.hash;
    console.log(location.hash);
    websocket.send(JSON.stringify({'tab' : tab}));
});
我有用console.log記錄每一次的 hash 變化,確定他有抓到 hash,然後用websocket.send寫到 JSON
ps. 這個 keyup 事件不一定要寫在websocket.onmessage裡。

步驟二

同樣在 client.js 將資料抓出來,然後做判斷:
JavaScript
//如果 data.tab 有資料
if (data.tab) {
    //因為 data.tab 抓到的資料是 #1, #2, #3... 這樣的值,為了只取數字,所以用 substring 去做截斷
    for(var x = 1; x &lt; data.tab.substring(1,2); x ++) {
        if(x == 1){
            $("div").css("display", "block");
          }
    };        
};

利用這樣的概念與方法,就可以簡單地在兩端互傳資料囉

有趣的 WebSocket 實例

一個由偉大的谷歌之神做的 WebSocket 互動網站,有興趣的朋友可以玩玩看,來體驗 WebSocket 是多麼的有趣
Super Sync Sports 是個利用 WebSocket 做的運動小遊戲,請先用 web 端瀏覽該網站,然後他會要你也用手機開啟這個網站,將 web 跟手機連線之後,就可以利用手機控制 web 介面來跑步、游泳,或是騎腳踏車。
而且還可以多人連線喔,超酷的 XDDD,大家有興趣不妨跟身旁的親朋好友一起玩樂比賽吧

程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...