簡介
由於油猴腳本只用一個JS文檔,因而相對於ChromeExtentions比較簡單。因此便從油猴腳本開始,首先基本的文件架構是:
// ==UserScript==
// @name New Script
// @namespace Violentmonkey Scripts
// @match http://ju.outofmemory.cn/entry/360333
// @grant none
// ==/UserScript==
其中一些屬性的含義:
@name
:
腳本名稱
@description
:
腳本功能的描述,顯示在腳本標題下面,必填項。
@namespace
:
@namespace
與 @name
這兩個屬性被作為腳本的唯一標識符,用戶腳本管理器根據它們來判斷一個腳本是否已安裝
@include
, @exclude
, @match
:
描述腳本會在哪些網站上運行。該列表會被解析和展示到腳本的簡介頁面,並用於腳本的分類。
@supportURL
:
該腳本的技術支持鏈接(如:錯誤反饋系統、論壇、電子郵件等),該鏈接將顯示在腳本的反饋頁面。
具體的注釋信息
腳本簡介
第一次編寫的腳本是微博超話自動簽到,主要借鑒bilibili助手的基本邏輯。本腳本功能實現每日自動簽到微博超話。
界面圖:
總結:
1.基於$.ajax()對Deferred理解。
主要借鑒$.ajax()引發的對Deferred的總結、回調、使用Promise封裝ajax()、Promise入門
ajax()是一種網頁中常用的異步操作,其寫法有兩種
//第一種,傳統寫法
$.ajax({
url:"/xxx",
type:"get",
success:function(data){//成功調用后的回調函數},
error:function(){//失敗調用后的回調函數}
});
//第二種
$.ajax({
url:"/xxx",
type:"get"
}).then(success,fail);//$.ajax()返回的是promise對象
Deffered是一種延遲對象 $.Deffered(),返回Deffered對象
done(fn) 當成功后調用fn
fail(fn) 當失敗后調用fn
then(done,fail) done和fail的總寫方式
always(fn) 不管成功或失敗都執行
resolve和reject執行,便執行done、fail、then、always方法。
resolve(value) 告訴對象執行done回調,value是參數,傳入done的回調函數 reject(value) 告訴對象執行fail回調,value是參數.傳入fail的回調函數
采用第二種寫法可以實現鏈式編程
const fn=()=>{const p =$.Deferred()
$.ajax({
url:"/xxx",
type:"get"
}).then(
(data)=>{p.resolve(data)},
()=>{p.reject()}
);
return p}
fn().then((data)=>{
//成功后的操作,data是resolve傳入的參數
//如果還需要異步執行,可以再定義Deferred對象,以此來實現有順序的執行
},()=>{
//失敗后的操作
})
2.跨域問題
由於JavaScript同源策略的限制,腳本只能讀取和所屬文檔來源相同的窗口和文檔。ajax請求時可能會請求不同源的網址。
首先以weibo.com為例說明同源
URL | 結果 | 原因 |
---|---|---|
https://www.weibo.com/dir1/other.html | Success | 同源 |
https://www.weibo.com/dir2/another.html | Success | 同源 |
https://m.weibo.com/1.html | Fail | 主機不同 |
http://www.weibo.com/2.html | Fail | 協議不同 |
https://www.weibo.com:80/3.html | Fail | 端口不同 |
這里用到了兩種:
-
document.domain
默認情況下,document.domain存放的是載入文檔的服務器的主機名,但不能設置為頂級域名,如www.weibo.com 可以設置為weibo.com 但不能設置為com
具有相同的document.domain就處在同域名的服務器上
-
CORS(跨域資源共享)
CROS是一種跨域訪問機制,可以實現Ajax的跨域訪問
需配置
//ajax中的配置
xhrFields.withCredentials = true
crossDomain = true
3.添加DOM元素
如果需要向網頁中添加按鍵、css樣式等等,就需要添加DOM元素,
如果需要引入CSS樣式鏈接
$('head').append('<link rel="stylesheet" href="樣式的鏈接" />')
上面的方法主要采取的jquery的方法,也可以用原生JS
const addCSS = (context) => {
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = context;
document.getElementsByTagName('head')[0].appendChild(style);
};//該方法用於添加CSS樣式
4.檢查類型
一種是通過typeof,可以判斷undefined、boolean、string、number、function
可以看到typeof對 對象、數組、null判定為object,有一定的缺陷。
另一種方法用Object.prototype.toString.call判斷
可以看到用此方法可以解決之前的混淆
除此之外,腳本也用到了isNaN()判斷是否為數字,如果為數字則為false,如果不是數字,則為true。
parseInt(string,radis)將其它類型轉換為Int類型,第二個參數為進制
注意: 只有字符串中的第一個數字會被返回。
注意: 開頭和結尾的空格是允許的。
注意:如果字符串的第一個字符不能被轉換為數字,那么 parseInt() 會返回 NaN。
5.localStorage
window的localStorage
和sessionStorage
儲存k/v對的數據,localStorage
中的鍵值對總是以字符串的形式存儲。
localStorage
用於長久保存整個網站數據。
方法:
localStorage.setItem('對象名','存儲的數據')
存儲
localStorage.getItem('對象名')
讀取
localStorage.removeItem('對象名')
移除
localStorage.clear()
移除所有
如果存儲的數據是JSON的類型,這可以用JSON.stringify()
和
JSON.parse()
來進行JSON對象和String對象的類型轉換
6.一些以后可能用到的方法
const tz_offset = new Date().getTimezoneOffset() + 480;
const ts_s = () => Math.round(ts_ms() / 1000);
const ts_ms = () => Date.now();
const checkNewDay = (ts) => {
// 檢查是否為新的一天,以UTC+8為准
const t = new Date(ts);
t.setMinutes(t.getMinutes() + tz_offset);
t.setHours(0, 0, 0, 0);
const d = new Date();
d.setMinutes(t.getMinutes() + tz_offset);
return (d - t > 86400e3);//86400秒為一天的時間
};
const runUntilSucceed = (callback, delay = 0, period = 100) => {
setTimeout(() => {
if (!callback()) runUntilSucceed(callback, period, period);
}, delay);
//如果執行的函數返回值為空,就繼續執行,直到callback返回值
};
let API={
processing: 0,
ajax: (settings) => {
if (settings.xhrFields === undefined) settings.xhrFields = {};
settings.xhrFields.withCredentials = true;
jQuery.extend(settings, {
url: (settings.url.substr(0, 2) === '//' ? '' : '//weibo.com/') + settings.url,
method: settings.method || 'GET',
crossDomain: true,
dataType: settings.dataType || 'json'
});//jquery.extend用於對象的連接
const p = jQuery.Deferred();
API.runUntilSucceed(() => {
if (API.processing > 8) return false;
++API.processing;
return jQuery.ajax(settings).then((arg1, arg2, arg3) => {
--API.processing;
p.resolve(arg1, arg2, arg3);
return true;
}, (arg1, arg2, arg3) => {
--API.processing;
p.reject(arg1, arg2, arg3);
return true;
});
});
return p;
}
}