Promise基本使用 Promise是非同步編程的一種解決方案,用於一個非同步操作的最終完成(或失敗)及其結果值的表示,比傳統的回調函數方案更加合理。 var promise = new Promise((resolve, reject) => {/* executor函數 */ // ... som ...
Promise基本使用
Promise
是非同步編程的一種解決方案,用於一個非同步操作的最終完成(或失敗)及其結果值的表示,比傳統的回調函數方案更加合理。
var promise = new Promise((resolve, reject) => {/* executor函數 */
// ... some code
if (/* 非同步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then((value) => {
//success
}, (error) => {
//failure
})
簡單實用
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(2000).then((value) => {
console.log(value); //done
});
var timeoutID = scope.setTimeout(function, [delay, arg1, arg2, ...]);
arg1, ..., argN
可選
附加參數,一旦定時器到期,它們會作為參數傳遞給function
Promise
對象在創建後立即執行,then
方法指定的回調函數,將在當前腳本所有同步任務執行完才會執行。- 如果調用
resolve
函數和reject
函數時帶有參數,那麼它們的參數會被傳遞給回調函數。reject
函數的參數通常是Error
對象的實例,表示拋出的錯誤;resolve
函數的參數除了正常的值以外,還可能是另一個Promise
實例。
const p = new Promise((resolve,reject) => {
return reject(new Error('err')); //reject方法的作用,等同於拋出錯誤
//throw new Error('err');
});
p.then(null, (err) => {
console.log(err); //Err: err
});
//--------等價寫法---------
p.catch(err => {
console.log(err); //Err: err
})
一般總是建議,Promise
對象後面要跟catch
方法,這樣可以處理 Promise
內部發生的錯誤。catch
方法返回的還是一個 Promise
對象,因此後面還可以接著調用then
方法。
new Promise(() => {
throw new Error('err1');
})
.then(() => {console.log(1);})
.then(() => {console.log(2);})
.catch((err) => {
console.log(err); //Err: err1
throw new Error('err2');
})
.catch((err) => {console.log(err);})//Err: err2
Promise
對象的錯誤具有“冒泡”性質,會一直向後傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch
語句捕獲。 即:當前catch
方法可以捕獲上一個catch
方法(包括上一個catch
)到當前catch
(不包括當前catch
)方法之間所有的錯誤,如果沒有錯誤,則當前catch
方法不執行。
// bad
new Promise()
.then((data) => {/* success */ }, (err) => {/* error */ });
// good
new Promise()
.then((data) => { /* success */ })
.catch((err) => {/* error */ });
一般來說,不要在then
方法裡面定義Reject
狀態的回調函數(即then
的第二個參數),總是使用catch
方法。第二種寫法要好於第一種寫法,理由是第二種寫法可以捕獲前面then
方法執行中的錯誤,也更接近同步的寫法。
vue里的export default
export命令用於規定模塊的對外介面。
一個模塊就是一個獨立的文件。該文件內部的所有變數,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變數,就必須使用export關鍵字輸出該變數。
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
export
命令對外輸出了指定名字的變數(變數也可以是函數或類)
與export default
命令的區別:import命令接受一對大括弧,裡面指定要從其他模塊導入的變數名。大括弧裡面的變數名,必須與被導入模塊(profile.js)對外介面的名稱相同。
export default命令,為模塊指定預設輸出。
與export命令的區別:其他模塊載入該模塊時,import命令可以為該匿名函數指定任意名字。
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
new VUE()
-
【Vue.config】 各種全局配置項
-
【Vue.util】 各種工具函數,還有一些相容性的標誌位
-
【Vue.set/delete】
-
【Vue.nextTick】
-
【Vue.options】 這個options和用來構造實例的options不一樣。這個是Vue預設提供的資源(組件指令過濾器)。
-
【Vue.use】 通過initUse方法定義
-
【Vue.mixin】 通過initMixin方法定義
-
【Vue.extend】通過initExtend方法定義
new Vue({
render: h => h(App),
}).$mount("#app")
render函數是vue通過js渲染dom結構的函數createElement,約定可以簡寫為h
實際縮寫前為:
render:function(createElement){
return createElement(App);
}
實際渲染
import App from './App'
import Vue from 'vue'
new Vue({
el:'#root',
template:'<App></App>',
components:{
App
}
})
在Vue構造函數時,需要配置一個el屬性,如果沒有沒有el屬性時,可以使用.$mount('#app')進行掛載。
// 配置了el屬性:
new Vue({
el:"#app",
router
});
// 如果沒有配置el屬性,可以使用手動掛載$mount("#app")
new Vue({
router
}).$mount('#app');
// 該方法是直接掛載到入口文件index.html 的 id=app 的dom 元素上的
render:h=>h(App)
1、ES6的寫法,表示Vue實例選項對象的render方法作為一個函數,接受傳入的參數h函數,返回h(App)的函數調用結果
2、Vue在創建Vue實例時,通過調用render方法來渲染實例的DOM樹
3、Vue在調用render方法時,會傳入一個createElement函數作為參數,也就是這裡的h的實參是createElement函數,然後createElement會以App為參數進行調用。
Vue.use()的作用及原理
官方對 Vue.use() 方法的說明:通過全局方法 Vue.use() 使用插件,Vue.use 會自動阻止多次註冊相同插件,它需要在你調用 new Vue() 啟動應用之前完成,Vue.use() 方法至少傳入一個參數,該參數類型必須是 Object 或 Function,如果是 Object 那麼這個 Object 需要定義一個 install 方法,如果是 Function 那麼這個函數就被當做 install 方法。在 Vue.use() 執行時 install 會預設執行,當 install 執行時第一個參數就是 Vue,其他參數是 Vue.use() 執行時傳入的其他參數。就是說使用它之後調用的是該組件的install 方法。
Vue.use
是用來安裝插件的。
它在使用時實際是調用了該插件的install方法,所以引入的當前插件如果含有install方法我們就需要使用Vue.use(),例如在Vue中引用Element如下:
import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element)
因為在Element源碼中會暴露除install方法,所以才需要用Vue.use()引入。
例如:
vueRouter需要在install方法,對Vue實例做一些自定義化的操作:比如在vue.prototype中添加$router、$route屬性、註冊
而axios是基於Promise封裝的庫,是完全獨立於Vue的,根本不需要掛載在Vue上也能實現發送請求。
vue-router 為什麼需要放到 new Vue({router}) options 里
插件通常用來為 Vue 添加全局功能。插件的功能範圍沒有嚴格的限制——一般有下麵幾種:
添加全局方法或者屬性。如: vue-custom-element
添加全局資源:指令/過濾器/過渡等。如 vue-touch
通過全局混入來添加一些組件選項。如 vue-router
添加 Vue 實例方法,通過把它們添加到 Vue.prototype 上實現。
一個庫,提供自己的 API,同時提供上面提到的一個或多個功能。如 vue-router
使用插件也很簡單,通過全局方法 Vue.use()
使用插件,註意它的調用需要在 new Vue()
之前。
但是在使用 vue-router
插件時還需要增加一個 options
:
// 調用 `router.install(Vue)`
Vue.use(router)
new Vue({
// ...組件選項
router
})
hash 路由和 history 路由
- hash 路由:監聽 url 中 hash 的變化,然後渲染不同的內容,這種路由不向伺服器發送請求,不需要服務端的支持;
- history 路由:監聽 url 中的路徑變化,需要客戶端和服務端共同的支持;
hash
—— 即地址欄 URL 中的 # 符號
比如這個 URL:http://www.aaa.com/#/hello,hash 的值為 #/hello。它的特點在於:hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對後端完全沒有影響,因此改變 hash 不會重新載入頁面。
history
—— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定瀏覽器支持)
這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端發送請求。
Hash 模式是使用 URL 的 Hash 來模擬一個完整的 URL,因此當 URL 改變的時候頁面並不會重載。History 模式則會直接改變 URL,所以在路由跳轉的時候會丟失一些地址信息,在刷新或直接訪問路由地址的時候會匹配不到靜態資源。因此需要在伺服器上配置一些信息,讓伺服器增加一個覆蓋所有情況的候選資源,比如跳轉 index.html 什麼的
hash路由 優缺點
- 優點
- 實現簡單,相容性好(相容到
ie8
) - 絕大多數前端框架均提供了給予
hash
的路由實現 - 不需要伺服器端進行任何設置和開發
- 除了資源載入和
ajax
請求以外,不會發起其他請求
- 實現簡單,相容性好(相容到
- 缺點
- 對於部分需要重定向的操作,後端無法獲取
hash
部分內容,導致後臺無法取得url
中的數據, - 伺服器端無法準確跟蹤前端路由信息
- 對於需要錨點功能的需求會與目前路由機制衝突
- 對於部分需要重定向的操作,後端無法獲取
History(browser)路由 優缺點
- 優點
- 對於重定向過程中不會丟失
url
中的參數。後端可以拿到這部分數據 - 絕大多數前段框架均提供了
browser
的路由實現 - 後端可以準確跟蹤路由信息
- 可以使用
history.state
來獲取當前url
對應的狀態信息
- 對於重定向過程中不會丟失
- 缺點
- 相容性不如
hash
路由(只相容到IE10
) - 需要後端支持,每次返回
html
文檔
- 相容性不如
$route和$router的區別
1.$router是VueRouter的一個對象,通過Vue.use(VueRouter)和Vue構造函數得到一個router的實例對象,這個對象中是一個全局的對象,他包含了所有的路由,包含了許多關鍵的對象和屬性。
2.$route
是一個跳轉的路由對象,每一個路由都會有一個$route對象,是一個局部的對象,可以獲取對應的name,path,params,query等
全局事件匯流排
全局事件匯流排說到底就是個對象,我們通常就是用vm對象作為全局事件匯流排使用
把vm對象添加到Vue原型對象 就形成全局事件匯流排(vm)
1、所有的組件對象必須都能看得到這個匯流排對象,因此我們把這個對象放在了Vue原型
2、這個事件匯流排對象必須能調用$on和$emit方法(匯流排對象必須是Vue的實例化對象或者是組件對象)
1、vm.$on( event, callback )
監聽當前實例上的自定義事件。事件可以由vm.$emit觸發。回調函數會接收所有傳入事件觸發函數的額外參數。
2、vm.$emit( event, […args] )
觸發當前實例上的事件。附加參數都會傳給監聽器回調,如果沒有參數,形式為vm.$emit(event)
3、vm.$off( [event, callback] )
移除自定義事件監聽器。