中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

坪山網(wǎng)站開發(fā)軟件外包公司有前途嗎

坪山網(wǎng)站開發(fā),軟件外包公司有前途嗎,網(wǎng)站開發(fā)信息,贛州專業(yè)做網(wǎng)站文章目錄 寫給零基礎(chǔ)看的Vue極速掌握教程第1章 Vue簡(jiǎn)介1.1 Vue 概述1.2 MVVM 模式1.3 WebStorm開發(fā)工具1.3.1 WebStorm簡(jiǎn)介1.3.2 集成Vue開發(fā)調(diào)試工具 第2章 Vue的事件綁定2.1 Vue基本使用2.1.1 插值表達(dá)式2.1.2 注意事項(xiàng) 2.2 Vue事件綁定2.1.1 點(diǎn)擊事件2.2.2 鍵盤事件2.2.3 移…

文章目錄

  • 寫給零基礎(chǔ)看的Vue極速掌握教程
  • 第1章 Vue簡(jiǎn)介
    • 1.1 Vue 概述
    • 1.2 MVVM 模式
    • 1.3 WebStorm開發(fā)工具
      • 1.3.1 WebStorm簡(jiǎn)介
      • 1.3.2 集成Vue開發(fā)調(diào)試工具
  • 第2章 Vue的事件綁定
    • 2.1 Vue基本使用
      • 2.1.1 插值表達(dá)式
      • 2.1.2 注意事項(xiàng)
    • 2.2 Vue事件綁定
      • 2.1.1 點(diǎn)擊事件
      • 2.2.2 鍵盤事件
      • 2.2.3 移動(dòng)事件
    • 2.3 按鍵修飾符
      • 2.3.1 默認(rèn)的按鍵修飾符
      • 2.3.2 自定義按鍵修飾符
      • 2.3.3 自定義按鍵修飾符注意事項(xiàng)
      • 2.3.4 自定義別名
    • 2.4 事件修飾符
  • 第3章 Vue常用指令
    • 3.1 v-text與v-html
    • 3.2 v-for
    • 3.3 v-if與v-show
    • 3.4 MVVM雙向綁定
      • 3.4.1 v-bind
      • 3.4.2 v-model
  • 第4章 Vue的生命周期
    • 4.1 Vue的生命周期簡(jiǎn)介
    • 4.2 Vue的生命周期鉤子
      • 4.2.1 beforeCreate/created
      • 4.2.2 beforeMount/mounted
      • 4.2.3 beforeUpdate/updated
      • 4.2.4 beforeDestory/destroyed
  • 第5章 Vue的ajax
    • 5.1 vue-resource
    • 5.2 Promise
      • 5.2.1 回調(diào)地獄
      • 5.2.2 Promise的使用
      • 5.2.3 Promise改造Ajax請(qǐng)求
    • 5.2 axios
      • 5.2.1 搭建WEB工程
      • 5.2.2 使用axios發(fā)送請(qǐng)求
    • 5.3 axios配置
    • 5.4 axios攔截器

寫給零基礎(chǔ)看的Vue極速掌握教程

第1章 Vue簡(jiǎn)介

1.1 Vue 概述

是一套用于構(gòu)建用戶界面漸進(jìn)式框架。與其它大型框架不同的是,Vue 被設(shè)計(jì)為可以自底向上逐層應(yīng)用。Vue 的核心庫(kù)只關(guān)注視圖層,不僅易于上手,還便于與第三方庫(kù)或既有項(xiàng)目整合。另一方面,當(dāng)與現(xiàn)代化的工具鏈以及各種支持類庫(kù)結(jié)合使用時(shí),Vue 也完全能夠?yàn)閺?fù)雜的單頁(yè)應(yīng)用提供驅(qū)動(dòng)。

Vue.js 的目標(biāo)是通過盡可能簡(jiǎn)單的 API 實(shí)現(xiàn)響應(yīng)的數(shù)據(jù)綁定以及組合視圖組件

Vue3官網(wǎng):https://cn.vuejs.org/

Vue2官網(wǎng):https://v2.cn.vuejs.org/

1.2 MVVM 模式

MVVM(Model-View-ViewModel)即:模型-視圖-視圖模型,是一種軟件架構(gòu)設(shè)計(jì)模式,常用于簡(jiǎn)化用戶界面的開發(fā)。其核心在于將數(shù)據(jù)模型(Model)和視圖(View)之間的交互抽象化,通過一個(gè)稱為ViewModel的組件來實(shí)現(xiàn)。ViewModel負(fù)責(zé)將Model中的數(shù)據(jù)轉(zhuǎn)換成視圖可以使用的格式,并且暴露給視圖操作的數(shù)據(jù)和命令。

ViewModel 需要做兩件事情:

(1)需要監(jiān)聽Model的數(shù)據(jù)變化,將Model上的任何數(shù)據(jù)變化渲染到View上。

(2)需要監(jiān)聽View上的任何數(shù)據(jù)變化,將View上的任何變動(dòng)寫入Model中。

  • Model:后端響應(yīng)的數(shù)據(jù),前端將其使用Model接收(封裝)
  • View:我們看到的各種HTML控件,負(fù)責(zé)使用HTML控件來渲染已經(jīng)得到的數(shù)據(jù)。
  • ViewModel:將后端響應(yīng)的數(shù)據(jù)(Model)綁定(渲染)到視圖(View)中,其次,當(dāng)視圖控件進(jìn)行數(shù)據(jù)修改時(shí),VM能監(jiān)聽到數(shù)據(jù)的修改,將用戶更新的數(shù)據(jù)直接更新到Model中。

Vue.js 是一個(gè)提供了 MVVM 風(fēng)格的雙向數(shù)據(jù)綁定的 Javascript 庫(kù),專注于View 層。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel 負(fù)責(zé)連接 View 和 Model,保證視圖和數(shù)據(jù)的一致性,這種輕量級(jí)的架構(gòu)讓前端開發(fā)更加高效、便捷。

我們可以回顧一下之前的原生JS/JQ代碼是如何渲染數(shù)據(jù)的:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title></head><body><!-- View: 視圖 --><select name="" id="depts"></select></body></html><script type="text/javascript">$.get("/dept/findAll",function(res){				// res: 后端響應(yīng)的數(shù)據(jù)(Model)var deptHtml="";for(var dept of res){				deptHtml+="<option value="+dept.id+">"+dept.name+"</option>";}// 更新視圖(View)$("#depts").html(deptHtml);})
</script>

1.3 WebStorm開發(fā)工具

1.3.1 WebStorm簡(jiǎn)介

WebStorm 是JetBrains 公司旗下一款 JavaScript 開發(fā)工具。已經(jīng)被廣大中國(guó)JS開發(fā)者譽(yù)為“Web前端開發(fā)神器”、“最強(qiáng)大的HTML5編輯器”、“最智能的JavaScript IDE”等。與IntelliJ IDEA同源,繼承了IntelliJ IDEA強(qiáng)大的JS部分的功能。

1.3.2 集成Vue開發(fā)調(diào)試工具

vue-devtools是一款基于chrome游覽器的插件,用于調(diào)試vue應(yīng)用,這可以極大地提高我們的調(diào)試效率。在Edge瀏覽器的地址欄上輸入"edge://extensions/",回車,進(jìn)入Edge瀏覽器全局設(shè)置頁(yè)面,如圖所示。

點(diǎn)擊“獲取 Microsoft Edge 擴(kuò)展”,搜索“vue devtools”,如圖所示。

編寫一個(gè)Vue案例:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/vue.js"></script></head><body><div id="app">{{msg}}</div></body><script>new Vue({el: "#app",data: {msg: "hello Vue!"}})
</script></html>

按下F12,打開瀏覽器的控制臺(tái),可以觀察Vue插件。

發(fā)現(xiàn)多了一個(gè)Vue調(diào)試工具的菜單欄;

第2章 Vue的事件綁定

2.1 Vue基本使用

Vue.js 是一個(gè)用于構(gòu)建用戶界面的漸進(jìn)式JavaScript框架。它提供了一套聲明式的渲染數(shù)據(jù)到DOM的系統(tǒng)(其底層依賴于Vue提供的VM組件),以及組件化的開發(fā)模式。Vue.js 通過指令來擴(kuò)展HTML的功能,使得開發(fā)者能夠以聲明式的方式將DOM的綁定至底層Vue實(shí)例的數(shù)據(jù)上。

2.1.1 插值表達(dá)式

Vue.js 中的插值表達(dá)式是一種簡(jiǎn)潔的方式,用來在模板中顯示數(shù)據(jù)模型的變化。最常用的插值表達(dá)式是雙大括號(hào) {{ }},它可以插入數(shù)據(jù)模型中變量的值。

  • 使用示例:

當(dāng)在模板中使用雙大括號(hào) {{ }} 包裹一段表達(dá)式時(shí),Vue 會(huì)計(jì)算這段表達(dá)式的值,并將其轉(zhuǎn)換為字符串然后插入到 DOM 中。例如:

<span>{{ message }}</span>

如果 Vue 實(shí)例的數(shù)據(jù)(data)中有 message 屬性,那么該屬性的值將被渲染到頁(yè)面上。

插值表達(dá)式中可以包含任何有效的 JavaScript 表達(dá)式,包括變量引用、字符串連接、算術(shù)運(yùn)算等。

例如:

<p>{{ firstName + ' ' + lastName }}</p><p>{{ 1 + 2 }}</p><p>{{ ok ? 'YES' : 'NO' }}</p>

小練習(xí):

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script></head><body><!-- 準(zhǔn)備一個(gè)容器 --><div id="box"><h3>number:{{number}}</h3><h3>message:{{message}}</h3><h3>flag:{{flag}}</h3><h3>car:{{car}}</h3><h3>season:{{season}}</h3></div></body><script type="text/javascript">// 是否開啟devtools調(diào)試工具(開發(fā)版本默認(rèn)為true,生產(chǎn)版本默認(rèn)為false)Vue.config.devtools = true;new Vue({ // 創(chuàng)建一個(gè)Vue實(shí)例el: "#box", // 通過id選擇器選擇某個(gè)控件(代碼Vue接管這片區(qū)域)data: { // Vue中存放數(shù)據(jù)的地方(Model)number: 100,message: "Hello Vue!",flag: true,car: {brand: "長(zhǎng)安汽車",name: "長(zhǎng)安CS95",price: 158000},season: ["Spring", "Summer", "Autumn", "Winter"]}})</script></html>

2.1.2 注意事項(xiàng)

一個(gè)Vue只能綁定一個(gè)組件,即使選擇器可以選擇多個(gè)組件,那么也不會(huì)生效;

<body><div class="box">{{msg}}</div><div class="box">{{msg}}</div><script type="text/javascript">new Vue({el: ".box",				// 通過class選擇器選擇組件data: {msg:"Hello Vue!"}})</script></body>

當(dāng)然,我們也可以創(chuàng)建多個(gè)Vue實(shí)例來接管多個(gè)組件。

<body>
<div id="box1">{{msg}}
</div><div id="box2">{{msg}}
</div><script type="text/javascript">new Vue({el: "#box1",				// 通過class選擇器選擇組件data: {msg:"Hello Vue!"}})new Vue({el: "#box2",				// 通過class選擇器選擇組件data: {msg:"Hello Vue!"}})
</script></body>

2.2 Vue事件綁定

在Vue中提供 v-on 命令用于監(jiān)聽 DOM 事件,并在事件觸發(fā)時(shí)執(zhí)行一些 JavaScript 代碼。它可以在 Vue 模板中被用來響應(yīng)用戶操作,如點(diǎn)擊按鈕、輸入文本等。可以直接在 HTML 元素上使用 v-on 指令來綁定一個(gè)事件監(jiān)聽器到這個(gè)元素上的某個(gè)事件上。最簡(jiǎn)單的形式是將一個(gè)方法名(字符串)作為表達(dá)式傳入 v-on 指令。

  • 示例代碼:
<button v-on:click="doSomething">點(diǎn)擊我</button>

當(dāng)用戶點(diǎn)擊按鈕時(shí),將會(huì)調(diào)用 Vue 實(shí)例中的 methods 屬性里定義的 doSomething 方法。

  • 簡(jiǎn)寫方式:

為了簡(jiǎn)化書寫,Vue 還提供了一個(gè)簡(jiǎn)短的語法來代替完整的 v-on 寫法。只需要使用 @ 符號(hào)加上事件名即可。

<button @click="doSomething">點(diǎn)擊我</button>

vue提供的事件非常多,幾乎支持所有的原生JS事件,采用v-on:的方式監(jiān)聽。常用的Vue事件如下。

事件類型描述
click當(dāng)用戶點(diǎn)擊鼠標(biāo)按鈕時(shí)調(diào)用。
dblclick當(dāng)用戶雙擊鼠標(biāo)按鈕時(shí)調(diào)用。
mousedown當(dāng)用戶按下鼠標(biāo)按鈕時(shí)調(diào)用。
mouseup當(dāng)用戶釋放鼠標(biāo)按鈕時(shí)調(diào)用。
mouseover當(dāng)用戶將鼠標(biāo)指針移到元素上時(shí)調(diào)用。
mouseout當(dāng)用戶將鼠標(biāo)指針從元素或其子元素移開時(shí)調(diào)用。
mouseenter當(dāng)用戶將鼠標(biāo)指針移到元素上時(shí)調(diào)用(不包括子元素)。
mouseleave當(dāng)用戶將鼠標(biāo)指針從元素或其子元素移開時(shí)調(diào)用。
contextmenu當(dāng)用戶右擊(或執(zhí)行類似操作)來打開上下文菜單時(shí)調(diào)用。
keydown當(dāng)用戶按下鍵盤上的鍵時(shí)調(diào)用。
keypress當(dāng)用戶按下一個(gè)或多個(gè)鍵并且產(chǎn)生字符值時(shí)調(diào)用。
keyup當(dāng)用戶釋放鍵盤上的鍵時(shí)調(diào)用。
submit當(dāng)表單提交時(shí)調(diào)用。
focus當(dāng)元素獲得焦點(diǎn)時(shí)調(diào)用。
blur當(dāng)元素失去焦點(diǎn)時(shí)調(diào)用。
change當(dāng)域的內(nèi)容被改變時(shí)調(diào)用。
input每當(dāng)輸入字段發(fā)生變化時(shí)調(diào)用。
reset當(dāng)表單被重置時(shí)調(diào)用。
select當(dāng)用戶選擇一些文本或更改了對(duì)象的選擇時(shí)調(diào)用。
touchstart觸摸開始時(shí)調(diào)用。
touchmove觸摸移動(dòng)時(shí)調(diào)用。
touchend觸摸結(jié)束時(shí)調(diào)用。
touchcancel觸摸被中斷時(shí)調(diào)用。

2.1.1 點(diǎn)擊事件

點(diǎn)擊事件分為單機(jī)事件與雙擊事件,在Vue中分別采用click和dbclick來監(jiān)聽。

  • v-on:click:單機(jī)事件。
  • v-dbclick:雙擊事件。

示例代碼:

<body>
<div id="box"><h3>單擊事件</h3><p><a href="http://www.baidu.com" v-on:click="fun1">我是按鈕1</a></p><p><a href="http://www.baidu.com" v-on:click="fun2('hello')">我是按鈕2</a></p><p><a href="http://www.baidu.com" v-on:click="fun3">我是按鈕3</a></p><!-- v-on: 可以簡(jiǎn)寫成@ --><!-- 如果event參數(shù)在后面,則必須顯示的傳遞 --><p><a href="http://www.baidu.com" @click="fun4('hello',$event)">我是按鈕4</a></p><h3>雙擊事件</h3><p><button v-on:dblclick="fun5">雙擊事件</button></p></div><script type="text/javascript">new Vue({el: "#box",data: {},methods:{fun1:function(){alert(1)},fun2:function(msg){alert(msg)},fun3:function(event){				// Vue中定義的方法默認(rèn)會(huì)傳遞一個(gè)event事件alert(event)event.preventDefault();			// 阻止事件的默認(rèn)行為(跳轉(zhuǎn)頁(yè)面)},fun4:function(msg,event){alert(msg);alert(event);},fun5:function(){alert("雙擊事件!")}}})
</script></body>

2.2.2 鍵盤事件

  • v-on:keydown:鼠標(biāo)按下事件
  • v-on:keyup:鼠標(biāo)抬起事件

示例代碼:

<body><div id="box"><input type="text" v-on:keydown="down"><br> <!-- 鍵盤按下事件 --><input type="text" v-on:keyup="up"> <!-- 鍵盤抬起事件 --></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {down() { // 簡(jiǎn)寫方式console.log("鍵盤按下了")},up(){console.log("鍵盤抬起了")}}})</script></body>

2.2.3 移動(dòng)事件

  • v-on:mouseover:鼠標(biāo)移入事件
  • v-on:mouseout:鼠標(biāo)移出事件

示例代碼:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script></head><body><div id="box" style="width: 300px;height: 200px;background-color: gray;" v-on:mousemove="inter" v-on:mouseout="outer"></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {inter(){console.log("鼠標(biāo)移入了")},outer(){console.log("鼠標(biāo)移出了")}}})</script></body></html>

2.3 按鍵修飾符

2.3.1 默認(rèn)的按鍵修飾符

當(dāng)進(jìn)行鍵盤事件的監(jiān)聽時(shí),我們可以通過event事件中的keyCode或者key來判斷按下的是哪一個(gè)鍵,從而進(jìn)行針對(duì)性的處理;同時(shí)Vue也為一些常用的按鍵分配了按鍵修飾符(相當(dāng)于別名),這樣就可以更加方便的來監(jiān)聽指定的按鍵,Vue中常用的按鍵別名如下:

  • 回車 => enter
  • 刪除 => delete(捕獲“刪除”和“退格”鍵)
  • 退出 => esc
  • 空格 => space
  • 換行 => tab(沒有keyup事件,只有keydown事件)
  • 上 => up
  • 下 => down
  • 左 => left
  • 右 => right

示例代碼:

<body><div id="box"><p><input type="text" v-on:keyup="fun1"></p><p><input type="text" v-on:keyup.enter="fun2">enter</p><p><input type="text" v-on:keyup.delete="fun3">delete</p><p><input type="text" v-on:keyup.esc="fun4">esc</p><p><input type="text" v-on:keydown.tab="fun5">tab</p></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1(event){console.log(event.keyCode,"---",event.key)},fun2(){console.log("您按下了回車!")},fun3(){console.log("您按下了delete!")},fun4(){console.log("您按下了esc!")},fun5(){console.log("您按下了tab!")}}})</script></body>

2.3.2 自定義按鍵修飾符

針對(duì)于Vue未提供別名的按鍵,可以使用按鍵原始的key值去綁定,但注意要轉(zhuǎn)為短橫線命名

例如:CapsLock—>caps-lock

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script></head><body>
<div id="box"><p><input type="text" v-on:keyup="fun1"></p><p><input type="text" v-on:keyup.Control="fun2">ctrl</p><!-- 注意需要【短橫線命名】--><p><input type="text" v-on:keyup.caps-lock="fun3">CapsLock</p><p><input type="text" v-on:keyup.delete="fun4">delete</p></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1(event) {console.log(event.keyCode, "---", event.key)},fun2() {console.log("您按下了ctrl!")},fun3() {console.log("您按下了CapsLock!")},fun4() {console.log("您按下了delete或backspace鍵!")}}})
</script></body></html>

2.3.3 自定義按鍵修飾符注意事項(xiàng)

Vue自定義的按鍵修飾符修飾系統(tǒng)修飾鍵(用法特殊)時(shí):(ctrl、alt、shift、meta),其中ctrl鍵除外;

  • 配合keyup使用:按下修飾鍵的同時(shí),再按下其他鍵,隨后釋放其他鍵,事件才被觸發(fā)。
  • 配合keydown使用:正常觸發(fā)事件。

另外,例如某些鍵監(jiān)聽不了;因此我們一般都使用Vue自身提供的按鍵修飾符或者采用keyCode/key來判斷用戶按下的鍵;

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script></head><body><div id="box"><p><input type="text" v-on:keyup="fun1"></p><p><input type="text" v-on:keyup.Control="fun2">ctrl</p>		<p><input type="text" v-on:keyup.Alt="fun3">alt</p>				<!-- 監(jiān)聽keyup時(shí)需要按其他鍵才能觸發(fā)事件 --><p><input type="text" v-on:keyup.Shift="fun4">shift</p>		<!-- 監(jiān)聽keyup時(shí)需要按其他鍵才能觸發(fā)事件 --><p><input type="text" v-on:keyup.Meta="fun5">meta</p>			<!-- 監(jiān)聽keyup時(shí)需要按其他鍵才能觸發(fā)事件 --><p><input type="text" v-on:keydown.0="fun6">0</p>				<!-- 只能監(jiān)聽數(shù)字0 --></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1(event){console.log(event.keyCode,"---",event.key)},fun2(){console.log("您按下了ctrl!")},fun3(){console.log("您按下了alt!")},fun4(){console.log("您按下了shift!")},fun5(){console.log("您按下了windows!")},fun6(){console.log("您按下了數(shù)字0!")}}})</script></body></html>

2.3.4 自定義別名

Vue支持根據(jù)keyCode來擴(kuò)展自定義的按鍵,擴(kuò)展的自定義按鍵解決了系統(tǒng)按鍵需要搭配其他鍵才能觸發(fā)的問題(也有部分按鍵可能會(huì)有問題)

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script></head><body><div id="box"><p><input type="text" v-on:keyup="fun1"></p><p><input type="text" v-on:keyup.huiche="fun2">回車</p>		<p><input type="text" v-on:keyup.kongge="fun3">空格</p>		<p><input type="text" v-on:keyup.windows="fun4">windows</p>		</div><script type="text/javascript">Vue.config.keyCodes.huiche = 13 			Vue.config.keyCodes.kongge = 32 			Vue.config.keyCodes.windows = 91 			new Vue({el: "#box",data: {},methods: {fun1(event){console.log(event.keyCode,"---",event.key)},fun2(){console.log("您按下了回車")},fun3(){console.log("您按下了空格!")},fun4(){console.log("您按下了windows!")}}})</script></body></html>

2.4 事件修飾符

Vue中提供了簡(jiǎn)化了很多JS中的事件修飾符,Vue中的事件修飾符如下:

事件說明
prevent阻止默認(rèn)事件;
stop阻止事件冒泡;
capture使用事件的捕獲模式;
once事件只觸發(fā)一次;
self只有event.target是當(dāng)前操作的元素時(shí)才觸發(fā)事件;
passive事件的默認(rèn)行為立即執(zhí)行,無需等待事件回調(diào)執(zhí)行完畢;
left (2.2.0)只當(dāng)點(diǎn)擊鼠標(biāo)左鍵時(shí)觸發(fā)。
right(2.2.0)只當(dāng)點(diǎn)擊鼠標(biāo)右鍵時(shí)觸發(fā)。
middle(2.2.0)只當(dāng)點(diǎn)擊鼠標(biāo)中鍵時(shí)觸發(fā)。

(1)阻止默認(rèn)事件。

<body>
<div id="box"><!--a標(biāo)簽的默認(rèn)事件被阻止了,所以不會(huì)進(jìn)行鏈接跳轉(zhuǎn)--><h3>阻止默認(rèn)事件</h3><p><a href="http://www.baidu.com" v-on:click.prevent="fun1">百度一下</a></p></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1() {alert("Hello Baidu")}}})
</script></body>

(2)阻止冒泡事件。

<body>
<div id="box"><!-- 先點(diǎn)擊到blue,然后向上傳遞給上層的空間(red)--><h3>未阻止冒泡事件</h3><div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div><!--只有blue被觸發(fā)時(shí)間了,不會(huì)向上傳遞事件,red不會(huì)觸發(fā)點(diǎn)擊事件--><h3>阻止冒泡事件</h3><div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click.stop="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1() {console.log("red")},fun2() {console.log("blue")}}})
</script></body>

(3)事件捕捉。

<body>
<div id="box"><!--先blue(先捕捉到),再red--><h3>未進(jìn)行事件捕捉</h3><div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div><!--先bred(先捕捉到),再blue--><h3>進(jìn)行了事件捕捉</h3><div v-on:click.capture="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1() {console.log("red")},fun2() {console.log("blue")}}})
</script></body>

(4)self修飾符。

<body>
<div id="box"><!-- 默認(rèn)情況下,點(diǎn)擊了blue事件會(huì)進(jìn)行冒泡傳遞給red,但是用戶并非實(shí)際點(diǎn)擊red,而是冒泡傳遞過去的 --><h5>沒有使用self修飾符</h5><div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div><h5>使用了self修飾符</h5><!-- 只有真正的點(diǎn)擊自己時(shí)才觸發(fā)事件,不接收冒泡傳遞過來的事件 --><div v-on:click.self="fun1" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div></div></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1(event) {console.log(event.target)},fun2(event) {console.log(event.target)}}})
</script></body>

(6)左、右、中鍵點(diǎn)擊事件。

<body>
<div id="box"><h3>單擊事件</h3><button v-on:click.left="fun1">單擊左鍵</button><button v-on:click.right="fun2">單擊右鍵</button><button v-on:click.middle="fun3">單擊中鍵</button></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1() {console.log("您點(diǎn)擊了左鍵")},fun2(event) {console.log("您點(diǎn)擊了右鍵")event.preventDefault()  //阻止默認(rèn)事件(瀏覽器右鍵菜單)},fun3() {console.log("您點(diǎn)擊了中鍵")}}})
</script></body>
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script><style>li {height: 100px;}</style></head><body style="height: 1000px;">
<div id="box"><h3>阻止默認(rèn)事件</h3><p><a href="http://www.baidu.com" v-on:click.prevent="fun1">百度一下</a></p><h3>阻止事件冒泡</h3><div v-on:click="fun2" style="width: 150px;height: 150px;background-color: red;"><div v-on:click.stop="fun3" style="width: 100px;height: 100px;background-color: blue;"></div></div><h3>只觸發(fā)一次事件</h3><p><button v-on:click.once="fun4">我是按鈕</button></p><h5>事件捕獲</h5><!-- 默認(rèn)情況下,先進(jìn)行事件冒泡,再進(jìn)行事件捕獲capture: 先進(jìn)行事件捕獲,在進(jìn)行事件冒泡--><div v-on:click.capture="fun5('red')" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun6('blue')" style="width: 100px;height: 100px;background-color: blue;"></div></div><h5>self修飾符</h5><!-- 只有真正的點(diǎn)擊自己時(shí)才觸發(fā)事件(冒泡不能觸發(fā)事件) --><div v-on:click.self="fun7" style="width: 150px;height: 150px;background-color: red;"><div v-on:click="fun8" style="width: 100px;height: 100px;background-color: blue;"></div></div><h5>passvie</h5><!-- 事件的默認(rèn)行為立即執(zhí)行,無需等待事件回調(diào)執(zhí)行完畢; --><ul v-on:wheel.passvie="fun9" style="width: 200px;height: 200px;background-color: red;overflow: scroll;"><li>1</li><li>2</li><li>3</li><li>4</li></ul><h5>.left</h5><button v-on:click.left="fun10">left</button></div><script type="text/javascript">new Vue({el: "#box",data: {},methods: {fun1() {alert("Hello Baidu")},fun2() {alert("點(diǎn)擊了大的div")},fun3() {alert("點(diǎn)擊了小的div")},fun4() {console.log("按鈕點(diǎn)擊了")},fun5(color) {console.log(color)},fun6(color) {console.log(color)},fun7(event) {console.log(event.target)},fun8(event) {console.log(event.target)},fun9() {for (let i = 0; i < 100000; i++) {console.log('aaa')}},fun10() {console.log("left")}}})
</script></body></html>

第3章 Vue常用指令

3.1 v-text與v-html

  • v-text:不會(huì)渲染字符串里面的HTML內(nèi)容
  • v-html:會(huì)渲染字符串里面的HTML內(nèi)容
<body style="height: 1000px;">
<div id="box"><div v-text="txt"></div><div v-html="txt"></div></div><script type="text/javascript">new Vue({el: "#box",data: {txt: "<h1>Hello</h1>"}})
</script></body>

3.2 v-for

v-for指令用于遍歷使用;

<body>
<div id="box"><h3>遍歷數(shù)組</h3><ul><li v-for="(city,index) in cities">{{city}}---{{index}}</li></ul><h3>遍歷對(duì)象</h3><ul><li v-for="(val,key) in book">{{key}}---{{val}}</li></ul><h3>遍歷對(duì)象數(shù)組</h3><ul><!-- 遍歷對(duì)象數(shù)組時(shí),需要分配:key,取一個(gè)唯一且能標(biāo)識(shí)這條記錄的值(id) --><li v-for="(car,index) in cars" :key="car.id"><h3>index: {{index}}</h3><p>id:{{car.id}}</p><p>brand:{{car.brand}}</p><p>name:{{car.name}}</p></li></ul></div><script type="text/javascript">new Vue({el: "#box",data: {cities: ["廣州","杭州","蘭州","鄭州","福州"],book:{id:1,name:"《Java核心技術(shù)》",price: 28.8},cars:[{id:1,brand:"比亞迪",name:"比亞迪F3"},{id:2,brand:"五菱",name:"紅菱宏光S3"},{id:3,brand:"長(zhǎng)安",name:"長(zhǎng)安歐尚x7"}]}})
</script></body>

3.3 v-if與v-show

  • v-if:根據(jù)表達(dá)式的值來決定是否渲染元素(存不存在)
  • v-show:是根據(jù)表達(dá)式的值來決定是否顯示(display:none)

示例代碼:

<body>
<div id="app"><button @click="fun1">v-if效果</button><button @click="fun2">v-show效果</button><hr><!-- v-if決定元素是否存在DOM中--><span v-if="flag_if">小灰</span><hr><!-- v-show只是給元素添加了display:none樣式,元素仍然存在DOM中--><span v-show="flag_show">xiaohui</span></div><script>new Vue({el: "#app",data: {flag_if: false,flag_show: false},methods: {fun1: function() {this.flag_if = !this.flag_if;},fun2: function() {this.flag_show = !this.flag_show;}}});
</script></body>

3.4 MVVM雙向綁定

雙向綁定是MVVM模式中的一個(gè)重要特性,它允許數(shù)據(jù)在Model和View之間自動(dòng)同步。這意味著當(dāng)Model中的數(shù)據(jù)改變時(shí),這些變化會(huì)自動(dòng)反映到視圖上;同樣地,當(dāng)用戶通過視圖改變了數(shù)據(jù),這些變化也會(huì)被同步到Model中。這種機(jī)制極大地減少了手動(dòng)處理數(shù)據(jù)同步的代碼量,并且使得應(yīng)用程序更易于維護(hù)。

3.4.1 v-bind

v-bind 指令用于動(dòng)態(tài)地將屬性綁定到 Vue 實(shí)例的數(shù)據(jù)。當(dāng) Vue 實(shí)例的數(shù)據(jù)發(fā)生變化時(shí),v-bind 會(huì)自動(dòng)更新綁定的屬性值。但是這種綁定是單向的,即 Vue 實(shí)例中的數(shù)據(jù)發(fā)生變化后能夠即使更新到UI組件上,但是當(dāng)UI組件上的數(shù)據(jù)發(fā)生變化時(shí),并不能夠及時(shí)更新到Vue實(shí)例上。

它可以用來綁定任何 HTML 屬性,包括 class、style 以及其他標(biāo)準(zhǔn)屬性,如下:

  • v-bind:src 用于綁定圖片的 src 屬性。
  • v-bind:class 可以根據(jù)條件綁定類名。
  • v-bind:style 用于動(dòng)態(tài)設(shè)置樣式。

示例代碼:

<body>
<div id="app"><p v-bind:title="testTitle">綁定titlte屬性</p><!-- v-bind:title可以簡(jiǎn)寫成:title --><p :title="testTitle" :style="testStyle">綁定title和sytle屬性</p><input type="text" :value="testValue"><hr><a :href="url" v-bind::color="testColor">百度一下</a><hr><!--插入值寫法--><a v-bind={href:"http://www.baidu.com?id="+id}>百度一下</a><hr>
</div><script>new Vue({el: "#app",data: {testColor: "blue",testTitle: "我是通過v-bind綁定的title",testValue: "Hello",url: "http://www.baidu.com",id: 100,// 如果存在 - 必須使用駝峰命名或者使用''testStyle:{color:'red','font-weight':200}}});
</script></body>

3.4.2 v-model

v-model指令用于將Vue中的數(shù)據(jù)與組件中的數(shù)據(jù)進(jìn)行雙向綁定,當(dāng)Vue中的數(shù)據(jù)發(fā)生變化時(shí),立馬會(huì)渲染到組件上,當(dāng)組件上的值發(fā)生變化時(shí),會(huì)立馬更新到Vue中;這使得用戶輸入能夠直接反映到數(shù)據(jù)模型中,同時(shí)數(shù)據(jù)模型的變化也能立即反映在表單輸入上。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title><script src="js/vue.js" type="text/javascript" charset="utf-8"></script></head><body>
<div id="app"><input type="text" v-model:value="testValue">
</div><script>new Vue({el: "#app",data: {testValue:"aaa"}});
</script></body></html>

第4章 Vue的生命周期

4.1 Vue的生命周期簡(jiǎn)介

每個(gè) Vue 實(shí)例在被創(chuàng)建之前都要經(jīng)過一系列的初始化過程.

vue在生命周期中共有:beforeCreate、created、beforeMount、mountedbeforeUpdate、updatedbeforeDestory、destroyed8個(gè)狀態(tài);

4.2 Vue的生命周期鉤子

4.2.1 beforeCreate/created

  • beforeCreate:Vue生命周期的第一個(gè)函數(shù),在Vue對(duì)象創(chuàng)建之前執(zhí)行,初始化Vue自身的事件、注冊(cè)Vue示例的生命周期函數(shù)等,在該階段props、data、method都處于不可用狀態(tài);
    • 1)創(chuàng)建VUE對(duì)象之前執(zhí)行
    • 2)data中的數(shù)據(jù)還未初始化
    • 3)el還未關(guān)聯(lián)到對(duì)應(yīng)的id(還未掛載DOM)
    • 4){{}}表達(dá)式中的內(nèi)容還沒更新(真實(shí)DOM還未渲染)
  • created:創(chuàng)建VUE對(duì)象之后執(zhí)行,該階段Vue示例已經(jīng)被創(chuàng)建成功,初始化了props、data、methods等功能;但是Vue還未掛載dom元素(還未進(jìn)行綁定)
    • 1)創(chuàng)建VUE對(duì)象之后執(zhí)行
    • 2)data中的數(shù)據(jù)已經(jīng)初始化
    • 3)el還未關(guān)聯(lián)到對(duì)應(yīng)的id
    • 4){{}}表達(dá)式中的內(nèi)容還沒更新(真實(shí)DOM還未渲染)

【示例代碼1-觀察dom的變化】

<body>
<div id="box">{{message}}
</div><script>new Vue({el: "#box",data: {message: 'Hello World'},// 在beforeCreate階段的Vue,數(shù)據(jù)未初始化、dom未掛載、dom也未渲染beforeCreate: function () {console.log('創(chuàng)建vue實(shí)例前【beforeCreate】');console.log('data 數(shù)據(jù):' + this.message);			// undefinedconsole.log('掛載的對(duì)象:' + this.$el);				// undefinedconsole.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);		// {{message}}console.log('------------------');},// 在created階段的Vue,數(shù)據(jù)已經(jīng)初始化、但dom未掛載、dom也未渲染created: function () {console.log('創(chuàng)建vue實(shí)例后【created】');console.log('data 數(shù)據(jù):' + this.message);				// Hello Worldconsole.log('掛載的對(duì)象:' + this.$el);					// undefinedconsole.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);		// {{message}}console.log('------------------');}});
</script></body>

【示例代碼2-調(diào)用Vue數(shù)據(jù)】

<body>
<div id="box">{{message}}
</div><script>new Vue({el: "#box",data: {message: 'Hello World'},methods: {method() {console.log("method running...");}},beforeCreate: function () {console.log('創(chuàng)建vue實(shí)例前【beforeCreate】');// Vue實(shí)例還未創(chuàng)建成功,不能調(diào)用this.method();// Vue實(shí)例還未創(chuàng)建成功,不能訪問數(shù)據(jù)(undefined)console.log(this.message);console.log('------------------');},created: function () {console.log('創(chuàng)建vue實(shí)例后【created】');// Vue實(shí)例已經(jīng)創(chuàng)建成功,可以調(diào)用Vue方法this.method();// Vue實(shí)例已經(jīng)創(chuàng)建成功,可以訪問數(shù)據(jù)console.log(this.message);console.log('------------------');}});
</script></body>

4.2.2 beforeMount/mounted

  • beforeMount:對(duì)象掛載之前執(zhí)行,此時(shí)el已經(jīng)關(guān)聯(lián)到對(duì)應(yīng)對(duì)象,但{{}}表達(dá)式還未加載(掛載了,但還沒完全掛載)
    • 1)對(duì)象掛載之前執(zhí)行
    • 2)data中的數(shù)據(jù)已經(jīng)初始化
    • 3)el已經(jīng)關(guān)聯(lián)到對(duì)應(yīng)對(duì)象(掛載了DOM)
    • 4){{}}表達(dá)式中的內(nèi)容還沒更新(真實(shí)DOM還未渲染)
  • mounted:對(duì)象掛載之后執(zhí)行,此時(shí){{}}表達(dá)已經(jīng)加載,執(zhí)行完mounted之后開始正常執(zhí)行js代碼
    • 1)對(duì)象掛載之后執(zhí)行
    • 2)data中的數(shù)據(jù)已經(jīng)初始化
    • 3)el已經(jīng)關(guān)聯(lián)到對(duì)應(yīng)對(duì)象
    • 4){{}}表達(dá)式中的內(nèi)容已經(jīng)更新(真實(shí)DOM已經(jīng)渲染)

【示例代碼1-觀察dom的變化】

<body>
<div id="box">{{message}}
</div><script>var vm = new Vue({el: "#box",data: {message: 'Hello World'},// 在beforeMount階段的Vue,數(shù)據(jù)已經(jīng)初始化、dom已經(jīng)掛載、但dom未渲染beforeMount: function () {console.log('掛載到dom前【beforeMount】');console.log('data 數(shù)據(jù):' + this.message);			// Hello Worldconsole.log('掛載的對(duì)象:' + this.$el);				// [object HTMLDivElement]console.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);		// {{message}}console.log('------------------');},// 在mounted階段的Vue,數(shù)據(jù)已經(jīng)初始化、dom已經(jīng)掛載、dom也已經(jīng)渲染mounted: function () {console.log('掛載到dom后【mounted】');console.log('data 數(shù)據(jù):' + this.message);			// Hello Worldconsole.log('掛載的對(duì)象:' + this.$el);				// [object HTMLDivElement]console.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);		// Hello Worldconsole.log('------------------');}});
</script></body>

4.2.3 beforeUpdate/updated

當(dāng)修改了Vue中的數(shù)據(jù)時(shí)將會(huì)觸發(fā)beforeUpdate與updated方法。

  • beforeUpdate:Vue數(shù)據(jù)更新前執(zhí)行,此時(shí)data中的數(shù)據(jù)已經(jīng)更新,但是{{}}表達(dá)式中引用的還沒有更新(還未渲染到DOM上)。
  • updated:Vue數(shù)據(jù)更新后執(zhí)行,{{}}表達(dá)式中引用也更新。

【示例代碼-觀察數(shù)據(jù)變更前后的值】

<body>
<div id="box">{{message}}<br><button v-on:click="fun1()">改變數(shù)據(jù)</button></div><script>var vm = new Vue({el: "#box",data: {message: 'Hello World'},methods: {fun1() {this.message = Math.random();}},// 當(dāng)修改了Vue中的數(shù)據(jù)時(shí),beforeUpdate方法中的dom還是為渲染之前的,但Vue中的數(shù)據(jù)已經(jīng)修改beforeUpdate: function () {console.log('數(shù)據(jù)變化更新前【beforeUpdate】');console.log('data 數(shù)據(jù):' + this.message);console.log('掛載的對(duì)象:' + this.$el);console.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);console.log('------------------');},// 當(dāng)修改了Vue中的數(shù)據(jù)時(shí),updated方法中的dom已經(jīng)更新為最新的數(shù)據(jù)updated: function () {console.log('數(shù)據(jù)變化更新后【updated】');console.log('data 數(shù)據(jù):' + this.message);console.log('掛載的對(duì)象:' + this.$el);console.log('真實(shí)dom結(jié)構(gòu):' + document.getElementById('box').innerHTML);console.log('------------------');}});</script></body>

4.2.4 beforeDestory/destroyed

  • beforeDestory:vue對(duì)象銷毀前執(zhí)行,在該方法中,Vue中注冊(cè)的組件、偵聽器、事件監(jiān)聽等都處于可用狀態(tài),一般在此階段釋放其他資源
  • destroyed:vue對(duì)象銷毀后執(zhí)行,在該方法中,已經(jīng)銷毀了Vue中注冊(cè)的組件、偵聽器、事件監(jiān)聽等;

【示例代碼-觀察Vue實(shí)例銷毀前后的變化】

<body>
<div id="box">{{message}}<hr><button @click="exit">銷毀VM</button></div><script>var vm = new Vue({el: "#box",data: {message: 'Hello World'},methods: {exit(){// 銷毀vmthis.$destroy()}},beforeDestroy: function () {console.log('--------beforeDestroy----------');},destroyed: function () {console.log('--------destroyed----------');}});
</script></body>

第5章 Vue的ajax

5.1 vue-resource

vue-resource是Vue.js的插件提供了使用XMLHttpRequest或JSONP進(jìn)行Web請(qǐng)求和處理響應(yīng)的服務(wù)。 曾經(jīng)是 Vue 社區(qū)廣泛使用的庫(kù)之一,用于發(fā)送 AJAX 請(qǐng)求和處理響應(yīng)。當(dāng)vue更新到2.0之后,作者就宣告不再對(duì)vue-resource更新,并且 Vue 官方推薦使用其他更現(xiàn)代的庫(kù)來處理 HTTP 請(qǐng)求,如 Axios 或者原生的 Fetch API等。

5.2 Promise

Promise 是 JavaScript 中的一種編程模式,用于處理異步操作。它提供了一種更加優(yōu)雅的方式來組織異步代碼,避免了回調(diào)地獄(callback hell)的問題,并且使得錯(cuò)誤處理更加一致。Promise 對(duì)象代表了一個(gè)最終會(huì)在未來完成(或失敗)的異步操作,所以在 Promise 返回給調(diào)用者的時(shí)候,操作往往還沒有完成,并且其結(jié)果值未知。

5.2.1 回調(diào)地獄

  • 回調(diào)函數(shù):當(dāng)一個(gè)函數(shù)作為參數(shù)傳入另一個(gè)參數(shù)中,并且它不會(huì)立即執(zhí)行,只有當(dāng)滿足一定條件后該函數(shù)才可以執(zhí)行,這種函數(shù)就稱為回調(diào)函數(shù)。我們熟悉的定時(shí)器和Ajax中就存在有回調(diào)函數(shù):
 //function(){console.log('執(zhí)行了回調(diào)函數(shù)')}就是回調(diào)函數(shù),它只有在3秒后才會(huì)執(zhí)行
setTimeout(function(){  console.log('執(zhí)行了回調(diào)函數(shù)');
},3000)  //3000毫秒
  • 異步任務(wù):與之相對(duì)應(yīng)的概念是“同步任務(wù)”,同步任務(wù)在主線程上排隊(duì)執(zhí)行,只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行下一個(gè)任務(wù)。異步任務(wù)不進(jìn)入主線程,而是進(jìn)入異步隊(duì)列,前一個(gè)任務(wù)是否執(zhí)行完畢不影響下一個(gè)任務(wù)的執(zhí)行。同樣,還拿定時(shí)器作為異步任務(wù)舉例:
setTimeout(function(){console.log('執(zhí)行了回調(diào)函數(shù)');
},3000)
console.log('111');

上述代碼的實(shí)際輸出順序?yàn)?#xff1a;“111”、“執(zhí)行了回調(diào)函數(shù)”。

  • 回調(diào)地獄:

根據(jù)前面我們可以得出一個(gè)結(jié)論:存在異步任務(wù)的代碼,不能保證能按照順序執(zhí)行,那如果我們非要代碼順序執(zhí)行呢?比如我需要先輸出“First”,再輸出“Second”,再輸出“Third”。我必須要這樣操作,才能保證順序正確:

setTimeout(function () {console.log("First");setTimeout(function () {console.log("Second");setTimeout(function () {console.log("Third");}, 3000);}, 4000);
}, 1000);

可以看到,代碼中的回調(diào)函數(shù)套回調(diào)函數(shù),居然套了3層,這種回調(diào)函數(shù)中嵌套回調(diào)函數(shù)的情況就叫做回調(diào)地獄。實(shí)際上,回調(diào)地獄的場(chǎng)景還是挺多見的,我們經(jīng)常需要先發(fā)送一段請(qǐng)求查詢到某些數(shù)據(jù)以當(dāng)做參數(shù)傳遞給下一個(gè)請(qǐng)求,這樣下一個(gè)請(qǐng)求就必須等上一個(gè)請(qǐng)求完畢后才能執(zhí)行。

5.2.2 Promise的使用

Promise 構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)會(huì)被立即執(zhí)行,所以我們稱之為起始函數(shù)。起始函數(shù)包含兩個(gè)函數(shù) resolve 和 reject,分別表示 Promise 成功和失敗的狀態(tài)。

起始函數(shù)執(zhí)行成功時(shí),它應(yīng)該調(diào)用 resolve 函數(shù)并傳遞成功的結(jié)果。當(dāng)起始函數(shù)執(zhí)行失敗時(shí),它應(yīng)該調(diào)用 reject 函數(shù)并傳遞失敗的原因。

Promise 構(gòu)造函數(shù)返回一個(gè) Promise 對(duì)象,該對(duì)象具有以下幾個(gè)方法:

  • then:用于處理 Promise 成功狀態(tài)的回調(diào)函數(shù)。
  • catch:用于處理 Promise 失敗狀態(tài)的回調(diào)函數(shù)。
  • finally:無論 Promise 是成功還是失敗,都會(huì)執(zhí)行的回調(diào)函數(shù)。

示例代碼:

// 創(chuàng)建一個(gè) Promise 對(duì)象
const promise = new Promise(function(resolve, reject) {// 進(jìn)行異步操作,該setTimeout函數(shù)在創(chuàng)建Promise對(duì)象時(shí)就已經(jīng)執(zhí)行setTimeout(() => {// 隨機(jī)生成成功或失敗if (Math.random() < 0.5) {// 如果成功(then)執(zhí)行resolve方法console.log('準(zhǔn)備執(zhí)行resolve');resolve('success');} else {// 如果失敗(catch)執(zhí)行reject方法console.log('準(zhǔn)備執(zhí)行reject');reject('error');}}, 1000);
});// 注冊(cè)成功和失敗的回調(diào)函數(shù)
promise.then(function (result){// result的值為resolve方法傳入的值console.log(result);
}).catch(function (error){// error的值為reject方法傳入的值console.log(error);
}).finally(function (){// 無論成功或失敗都會(huì)執(zhí)行console.log('Promise對(duì)象執(zhí)行完畢');
})console.log('程序執(zhí)行完畢');      // 因?yàn)镻romise對(duì)象是異步的,所以先輸出

執(zhí)行情況:

示例代碼:

new Promise(function (resolve, reject) {var a = 0;var b = 0;if (b == 0)reject("除數(shù)不能為0");elseresolve(a / b);
}).then(function (value) {console.log("a / b = " + value);
}).catch(function (err) {console.log(err);
}).finally(function () {console.log("End");
});console.log('程序執(zhí)行完畢');      // 因?yàn)镻romise對(duì)象是異步的,所以先輸出

執(zhí)行情況:

有了Promise,接下來我們可以改造一下回調(diào)地獄中的代碼了:

function print(delay, message) {return new Promise(function (resolve, reject) {setTimeout(function () {console.log(message);resolve();}, delay);});
}print(2000, "First").then(function () {return print(4000, "Second");
}).then(function () {print(3000, "Third");
});

Promise 對(duì)象一旦 Promise 被創(chuàng)建,它的狀態(tài)會(huì)在“待定”(pending)、“兌現(xiàn)”(fulfilled)和“拒絕”(rejected)之間轉(zhuǎn)變。狀態(tài)一旦轉(zhuǎn)變,就不會(huì)再變回之前的狀態(tài)。

  • 待定狀態(tài)(pedding):調(diào)用promise時(shí)(創(chuàng)建Promise對(duì)象時(shí)),一開始就呈現(xiàn)出等待狀態(tài),遇到resolve或者reject之前,都處于這個(gè)狀態(tài)。
  • 兌現(xiàn)狀態(tài)(fulfilled):在執(zhí)行了resolve后,promise則會(huì)從待定狀態(tài)變成兌現(xiàn)狀態(tài),后續(xù)會(huì)進(jìn)入.then 的回調(diào)函數(shù)中。
  • 拒絕狀態(tài)(rejected)在執(zhí)行了reject后,promise狀態(tài)會(huì)從待定狀態(tài)變成拒絕狀態(tài),后續(xù)會(huì)進(jìn)入.catch 的回調(diào)函數(shù)中。

5.2.3 Promise改造Ajax請(qǐng)求

Promise可以封裝一個(gè)異步操作,不阻塞當(dāng)前任務(wù)的執(zhí)行,利用這個(gè)特點(diǎn)我們可以用來封裝ajax請(qǐng)求,示例代碼如下:

const promise = new Promise((resolve, reject) => {
// 執(zhí)行異步操作(該方法在創(chuàng)建Promise對(duì)象時(shí)就已經(jīng)執(zhí)行)
if (/* 異步操作是否成功 */) {resolve(value);// 調(diào)用 resolve,代表 Promise 將返回成功的結(jié)果(其實(shí)就是調(diào)用then方法)} else {reject(error);// 調(diào)用 reject,代表 Promise 會(huì)返回失敗結(jié)果(其實(shí)就是調(diào)用catch方法)}
});

示例:

let getRequest = function (url) {// 使用Promise對(duì)象封裝一個(gè)ajax請(qǐng)求return new Promise((resolve, reject) => {$.ajax({url: url,type: "GET",success(result) {// 調(diào)用Promise的resolve方法resolve(result);},error(error) {// 調(diào)用Promise的reject方法reject(error);}});})
}// 模擬一個(gè)請(qǐng)求地址
var url = "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json";getRequest(url).then(function (result){console.log(result);
}).catch(function (error){console.log(error);
})console.log("程序執(zhí)行完畢");

5.2 axios

axios 是一個(gè)基于 promise 的 HTTP 客戶端,用于瀏覽器和 node.js。它提供了一種現(xiàn)代化的方式來進(jìn)行 HTTP 請(qǐng)求和接收響應(yīng),支持諸如攔截請(qǐng)求和響應(yīng)、轉(zhuǎn)換請(qǐng)求和響應(yīng)數(shù)據(jù)、取消請(qǐng)求等功能。axios 的設(shè)計(jì)使其易于使用,并且它已經(jīng)成為許多前端和后端開發(fā)者的首選庫(kù)之一。

  • axios的github地址:https://github.com/axios/axios
  • axios官方文檔:https://axios.nodejs.cn/docs/api_intro

axios的語法如表所示。

語法說明
axios(config)使用axios發(fā)送ajax請(qǐng)求
axios(url[, config])使用axios發(fā)送ajax請(qǐng)求
axios.request(config)使用axios發(fā)送ajax請(qǐng)求
axios.get(url[, config])發(fā)送get請(qǐng)求
axios.delete(url[, config])發(fā)送delete請(qǐng)求
axios.head(url[, config])發(fā)送head請(qǐng)求
axios.options(url[, config])發(fā)送options請(qǐng)求
axios.post(url[, data[, config]])發(fā)送post請(qǐng)求
axios.put(url[, data[, config]])發(fā)送put請(qǐng)求
axios.patch(url[, data[, config]])發(fā)送patch請(qǐng)求
axios.postForm(url[, data[, config]])使用 multipart/form-data 類型發(fā)起 post 請(qǐng)求
axios.putForm(url[, data[, config]])使用 multipart/form-data 類型發(fā)起 put 請(qǐng)求
axios.patchForm(url[, data[, config]])使用 multipart/form-data 類型發(fā)起 patch 請(qǐng)求
  • 示例代碼:

使用axois發(fā)送一個(gè)普通請(qǐng)求:

// 發(fā)起一個(gè) GET 請(qǐng)求 (默認(rèn)請(qǐng)求方式)
axios('/user/12345');// 發(fā)起一個(gè) GET 請(qǐng)求 (默認(rèn)請(qǐng)求方式)
axios('/user/12345');// 發(fā)起一個(gè) GET 請(qǐng)求 (默認(rèn)請(qǐng)求方式)
axios('/user/12345');

執(zhí)行GET請(qǐng)求:

// 向給定ID的用戶發(fā)起請(qǐng)求
axios.get('/user?ID=12345').then(function (response) {// 處理成功情況console.log(response);}).catch(function (error) {// 處理錯(cuò)誤情況console.log(error);}).finally(function () {// 總是會(huì)執(zhí)行});

攜帶參數(shù):

// 上述請(qǐng)求也可以按以下方式完成(可選)
axios.get('/user', {params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);}).finally(function () {// 總是會(huì)執(zhí)行});  

axios的響應(yīng)數(shù)據(jù)如下:

{// `data` 由服務(wù)器提供的響應(yīng)data: {},// `status` 來自服務(wù)器響應(yīng)的 HTTP 狀態(tài)碼status: 200,// `statusText` 來自服務(wù)器響應(yīng)的 HTTP 狀態(tài)信息statusText: 'OK',// `headers` 是服務(wù)器響應(yīng)頭// 所有的 header 名稱都是小寫,而且可以使用方括號(hào)語法訪問// 例如: `response.headers['content-type']`headers: {},// `config` 是 `axios` 請(qǐng)求的配置信息config: {},// `request` 是生成此響應(yīng)的請(qǐng)求// 在node.js中它是最后一個(gè)ClientRequest實(shí)例 (in redirects),// 在瀏覽器中則是 XMLHttpRequest 實(shí)例request: {}
}

5.2.1 搭建WEB工程

1)pom.xml:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.1.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>

2)entity:

package com.dfbz.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author lscl* @version 1.0* @intro:*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Book {private Integer id;private String name;private String author;
}

3)Controller:

package com.dfbz.controller;import com.dfbz.entity.Book;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;/*** @author lscl* @version 1.0* @intro:*/
@RestController
@RequestMapping("/book")
public class BookController {@PostMapping("/upload")public Map save(MultipartFile pic, HttpServletRequest request) throws Exception{String realPath = "D:/000";// 前端上傳的文件名稱String fileName = pic.getOriginalFilename();String suffix = fileName.substring(fileName.lastIndexOf("."));String newFileName = System.currentTimeMillis() + suffix;pic.transferTo(new File(realPath + "/" + newFileName));String url = "http://localhost:8080/upload/" + newFileName;return new HashMap(){{put("flag",true);put("message","圖片上傳成功");put("statusCode","200");put("picUrl",url);}};}@PostMappingpublic Map save(@RequestBody Book book){return new HashMap(){{put("flag",true);put("message","新增成功");put("book", book);put("statusCode","200");}};}@DeleteMapping("{id}")public Map delete(@PathVariable Integer id){return new HashMap(){{put("flag",true);put("message","刪除成功");put("id", id);put("statusCode","200");}};}@PutMapping("{id}")public Map update(@PathVariable Integer id,@RequestBody Book book){return new HashMap(){{put("flag",true);put("message","修改成功");put("id", id);put("book", book);put("statusCode","200");}};}@GetMappingpublic Map findAll(){int i=1/0;return new HashMap(){{put("flag",true);put("message","查詢成功");put("BookList",Arrays.asList(new Book(1,"《大學(xué)》","曾子"),new Book(2,"《莊子》","莊子"),new Book(2,"《道德經(jīng)》","老子")));put("statusCode","200");}};}
}

5.2.2 使用axios發(fā)送請(qǐng)求

demo01.html:

<body>
<div id="box"><button @click="save">save</button><hr><button @click="deleteById('10')">deleteById</button><hr><button @click="update('100')">update</button><hr><button @click="findAll">findAll</button><hr>
</div><script>new Vue({el: "#box",data: {},methods: {save: function () { // saveaxios({url: "/book",method: "post",data: {id: 1,name: "《論語》",author: "孔子"}}).then(function (response) {console.log(response);})},deleteById: function (id) { // deleteByIdaxios("/book/"+id,{method: "delete"}).then(function (response) {console.log(response);})},update: function (id) { // updateaxios.request({url: "/book/"+id,method: "put",data: {id: 2,name: "《孟子》",author: "孟子"}}).then(function (response) {console.log(response);})},findAll: function () { // findAll// 默認(rèn)發(fā)送GET請(qǐng)求axios("/book").then(function (response) {console.log(response);})}}})
</script></body>

demo02.html

<body>
<div id="box"><button @click="save">save</button><hr><button @click="deleteById('10')">deleteById</button><hr><button @click="update('100')">update</button><hr><button @click="findAll">findAll</button><hr>
</div><script>new Vue({el: "#box",data: {},methods: {save() {axios.post("/book", {id: 10, name: "《永樂大典》", author: "解縉"}).then(function (res) {// data是服務(wù)端響應(yīng)的數(shù)據(jù)console.log(res.data)}).catch(function (err) {console.log(err);});},deleteById(id) {axios.delete("/book/" + id).then(function (res) {console.log(res.data)}).catch(function (err) {console.log(err);});},update(id) {axios.put("/book/" + id, {id: 10, name: "《天工開物》", author: "宋應(yīng)星"}).then(function (res) {console.log(res.data)}).catch(function (err) {console.log(err);});},findAll() {axios.get("/book").then(function (res) {console.log(res.data)}).catch(function (err) {console.log(err);           // 異常信息});}}})
</script></body>

demo03.html

<body>
<div id="box"><input type="file" id="file"><button @click="upload">上傳文件</button></div><script>new Vue({el: "#box",data: {},methods: {upload() {// 構(gòu)建一個(gè)multipart/form-data的請(qǐng)求,用于上傳文件axios.postForm("http://localhost:8080/book/upload", // 上傳的文件對(duì)象,需要用FormData包裝一下{pic: document.getElementById("file").files[0]}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});}}})
</script></body>

5.3 axios配置

我們可以指定axios的默認(rèn)配置,這些配置將作用于每個(gè)axios請(qǐng)求。配置如下:

// 創(chuàng)建一個(gè)axios實(shí)例
const instance = axios.create({baseURL: 'https://some-domain.com/api/',timeout: 1000,headers: {'X-Custom-Header': 'foobar'}
});//可用的配置項(xiàng)如下:
{// `url` 是用于請(qǐng)求的服務(wù)器 URLurl: '/user',// `method` 是創(chuàng)建請(qǐng)求時(shí)使用的方法method: 'get', // 默認(rèn)值// `baseURL` 將自動(dòng)加在 `url` 前面,除非 `url` 是一個(gè)絕對(duì) URL。// 它可以通過設(shè)置一個(gè) `baseURL` 便于為 axios 實(shí)例的方法傳遞相對(duì) URLbaseURL: 'https://some-domain.com/api/',// `transformRequest` 允許在向服務(wù)器發(fā)送前,修改請(qǐng)求數(shù)據(jù)// 它只能用于 'PUT', 'POST' 和 'PATCH' 這幾個(gè)請(qǐng)求方法// 數(shù)組中最后一個(gè)函數(shù)必須返回一個(gè)字符串, 一個(gè)Buffer實(shí)例,ArrayBuffer,FormData,或 Stream// 你可以修改請(qǐng)求頭。transformRequest: [function (data, headers) {// 對(duì)發(fā)送的 data 進(jìn)行任意轉(zhuǎn)換處理return data;}],// `transformResponse` 在傳遞給 then/catch 前,允許修改響應(yīng)數(shù)據(jù)transformResponse: [function (data) {// 對(duì)接收的 data 進(jìn)行任意轉(zhuǎn)換處理return data;}],// 自定義請(qǐng)求頭headers: {'X-Requested-With': 'XMLHttpRequest'},// `params` 是與請(qǐng)求一起發(fā)送的 URL 參數(shù)// 必須是一個(gè)簡(jiǎn)單對(duì)象或 URLSearchParams 對(duì)象params: {ID: 12345},// `paramsSerializer`是可選方法,主要用于序列化`params`// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)paramsSerializer: function (params) {return Qs.stringify(params, {arrayFormat: 'brackets'})},// `data` 是作為請(qǐng)求體被發(fā)送的數(shù)據(jù)// 僅適用 'PUT', 'POST', 'DELETE 和 'PATCH' 請(qǐng)求方法// 在沒有設(shè)置 `transformRequest` 時(shí),則必須是以下類型之一:// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams// - 瀏覽器專屬: FormData, File, Blob// - Node 專屬: Stream, Bufferdata: {firstName: 'Fred'},// 發(fā)送請(qǐng)求體數(shù)據(jù)的可選語法// 請(qǐng)求方式 post// 只有 value 會(huì)被發(fā)送,key 則不會(huì)data: 'Country=Brasil&City=Belo Horizonte',// `timeout` 指定請(qǐng)求超時(shí)的毫秒數(shù)。// 如果請(qǐng)求時(shí)間超過 `timeout` 的值,則請(qǐng)求會(huì)被中斷timeout: 1000, // 默認(rèn)值是 `0` (永不超時(shí))// `withCredentials` 表示跨域請(qǐng)求時(shí)是否需要使用憑證withCredentials: false, // default// `adapter` 允許自定義處理請(qǐng)求,這使測(cè)試更加容易。// 返回一個(gè) promise 并提供一個(gè)有效的響應(yīng) (參見 lib/adapters/README.md)。adapter: function (config) {/* ... */},// `auth` HTTP Basic Authauth: {username: 'janedoe',password: 's00pers3cret'},// `responseType` 表示瀏覽器將要響應(yīng)的數(shù)據(jù)類型// 選項(xiàng)包括: 'arraybuffer', 'document', 'json', 'text', 'stream'// 瀏覽器專屬:'blob'responseType: 'json', // 默認(rèn)值// `responseEncoding` 表示用于解碼響應(yīng)的編碼 (Node.js 專屬)// 注意:忽略 `responseType` 的值為 'stream',或者是客戶端請(qǐng)求// Note: Ignored for `responseType` of 'stream' or client-side requestsresponseEncoding: 'utf8', // 默認(rèn)值// `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名稱xsrfCookieName: 'XSRF-TOKEN', // 默認(rèn)值// `xsrfHeaderName` 是帶有 xsrf token 值的http 請(qǐng)求頭名稱xsrfHeaderName: 'X-XSRF-TOKEN', // 默認(rèn)值// `onUploadProgress` 允許為上傳處理進(jìn)度事件// 瀏覽器專屬onUploadProgress: function (progressEvent) {// 處理原生進(jìn)度事件},// `onDownloadProgress` 允許為下載處理進(jìn)度事件// 瀏覽器專屬onDownloadProgress: function (progressEvent) {// 處理原生進(jìn)度事件},// `maxContentLength` 定義了node.js中允許的HTTP響應(yīng)內(nèi)容的最大字節(jié)數(shù)maxContentLength: 2000,// `maxBodyLength`(僅Node)定義允許的http請(qǐng)求內(nèi)容的最大字節(jié)數(shù)maxBodyLength: 2000,// `validateStatus` 定義了對(duì)于給定的 HTTP狀態(tài)碼是 resolve 還是 reject promise。// 如果 `validateStatus` 返回 `true` (或者設(shè)置為 `null` 或 `undefined`),// 則promise 將會(huì) resolved,否則是 rejected。validateStatus: function (status) {return status >= 200 && status < 300; // 默認(rèn)值},// `maxRedirects` 定義了在node.js中要遵循的最大重定向數(shù)。// 如果設(shè)置為0,則不會(huì)進(jìn)行重定向maxRedirects: 5, // 默認(rèn)值// `socketPath` 定義了在node.js中使用的UNIX套接字。// e.g. '/var/run/docker.sock' 發(fā)送請(qǐng)求到 docker 守護(hù)進(jìn)程。// 只能指定 `socketPath` 或 `proxy` 。// 若都指定,這使用 `socketPath` 。socketPath: null, // default// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http// and https requests, respectively, in node.js. This allows options to be added like// `keepAlive` that are not enabled by default.httpAgent: new http.Agent({ keepAlive: true }),httpsAgent: new https.Agent({ keepAlive: true }),// `proxy` 定義了代理服務(wù)器的主機(jī)名,端口和協(xié)議。// 您可以使用常規(guī)的`http_proxy` 和 `https_proxy` 環(huán)境變量。// 使用 `false` 可以禁用代理功能,同時(shí)環(huán)境變量也會(huì)被忽略。// `auth`表示應(yīng)使用HTTP Basic auth連接到代理,并且提供憑據(jù)。// 這將設(shè)置一個(gè) `Proxy-Authorization` 請(qǐng)求頭,它會(huì)覆蓋 `headers` 中已存在的自定義 `Proxy-Authorization` 請(qǐng)求頭。// 如果代理服務(wù)器使用 HTTPS,則必須設(shè)置 protocol 為`https`proxy: {protocol: 'https',host: '127.0.0.1',port: 9000,auth: {username: 'mikeymike',password: 'rapunz3l'}},// see https://axios-http.com/zh/docs/cancellationcancelToken: new CancelToken(function (cancel) {}),// `decompress` indicates whether or not the response body should be decompressed // automatically. If set to `true` will also remove the 'content-encoding' header // from the responses objects of all decompressed responses// - Node only (XHR cannot turn off decompression)decompress: true // 默認(rèn)值}

配置axios參數(shù):

// 創(chuàng)建一個(gè)axios實(shí)例,設(shè)置該實(shí)例的配置
const instance = axios.create({// 請(qǐng)求地址baseURL: 'http://localhost:8080/',// 請(qǐng)求超時(shí)時(shí)間timeout: 1000,// 自定義請(qǐng)求頭headers: {'X-Custom-Header-Username': 'xiaohui',"X-Custom-Header-Password":"admin"}
});// 設(shè)置全局的axios默認(rèn)配置
axios.defaults.baseURL = 'http://localhost:8080/';
axios.defaults.headers['X-Custom-Header-Username'] = "xiaolan";
axios.defaults.headers['X-Custom-Header-Password'] = "123456";

5.4 axios攔截器

axios 攔截器允許在請(qǐng)求被發(fā)送之前或響應(yīng)被處理之后執(zhí)行某些操作。攔截器可以用來添加全局的行為,例如在每個(gè)請(qǐng)求中自動(dòng)加入認(rèn)證信息、處理錯(cuò)誤響應(yīng)、重試失敗的請(qǐng)求等。通過使用攔截器,可以將一些通用的操作抽象出來,從而避免在每個(gè)請(qǐng)求中重復(fù)相同的代碼。

請(qǐng)求攔截器:

/*** 添加請(qǐng)求攔截器* config: 請(qǐng)求的配置對(duì)象*/
axios.interceptors.request.use(function (config) {// 在發(fā)送請(qǐng)求之前做些什么console.log("請(qǐng)求攔截器執(zhí)行...", config);// 添加自定義的請(qǐng)求頭信息config.headers["x-custom-header-username"] = "xiaohui";config.headers["x-custom-header-password"] = "admin";return config;
}, function (error) {// 對(duì)請(qǐng)求錯(cuò)誤做些什么return Promise.reject(error);
});

響應(yīng)攔截器:

/*** 添加響應(yīng)攔截器* response: 響應(yīng)對(duì)象*/
axios.interceptors.response.use(function (response) {// 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么// 2xx 范圍內(nèi)的狀態(tài)碼都會(huì)觸發(fā)該函數(shù)。console.log("響應(yīng)攔截器執(zhí)行...", response);response.data.msg = "我是響應(yīng)攔截器返回的消息";return response;
}, function (error) {// 超出 2xx 范圍的狀態(tài)碼都會(huì)觸發(fā)該函數(shù)。// 對(duì)響應(yīng)錯(cuò)誤做點(diǎn)什么return Promise.reject(error);
});
http://www.risenshineclean.com/news/42442.html

相關(guān)文章:

  • 中央最新指示停止核酸檢測(cè)東莞seo軟件
  • 很長(zhǎng)的網(wǎng)站域名怎么做短注冊(cè)安全工程師
  • 電子商務(wù)是電商嗎seo服務(wù)商
  • 個(gè)人網(wǎng)站建設(shè)收費(fèi)標(biāo)準(zhǔn)營(yíng)銷策略有哪幾種
  • 做外匯看的網(wǎng)站谷歌seo公司
  • 長(zhǎng)春建站平臺(tái)靜態(tài)網(wǎng)站模板
  • 上海網(wǎng)站建設(shè)升級(jí)開發(fā)做一個(gè)網(wǎng)站需要多少錢
  • 上門做指甲哪個(gè)網(wǎng)站百度seo工作室
  • dw做網(wǎng)站一般設(shè)為什么樣浙江網(wǎng)站建設(shè)制作
  • 國(guó)外網(wǎng)站怎么上合肥seo管理
  • 經(jīng)過開發(fā)建設(shè) 網(wǎng)站上線了長(zhǎng)尾關(guān)鍵詞排名工具
  • 網(wǎng)站建設(shè)以推廣外貿(mào)seo推廣
  • 做網(wǎng)站只用php不用html溫州seo
  • 給朋友做網(wǎng)站警察開找西安競(jìng)價(jià)托管
  • 浙江建設(shè)職業(yè)繼續(xù)教育學(xué)院網(wǎng)站如何搭建網(wǎng)站平臺(tái)
  • 大學(xué)生兼職網(wǎng)站開發(fā)畢設(shè)論文上海服務(wù)政策調(diào)整
  • 個(gè)人做短視頻網(wǎng)站東莞百度seo
  • 手機(jī)如何做微商城網(wǎng)站成都推廣系統(tǒng)
  • 網(wǎng)站設(shè)置了刷新限制關(guān)鍵詞代發(fā)排名首頁(yè)
  • 做國(guó)外產(chǎn)品描述的網(wǎng)站如何優(yōu)化搜索引擎的準(zhǔn)確性
  • 重慶建設(shè)廳網(wǎng)站如何自己編寫網(wǎng)站
  • 有贊可以做獨(dú)立網(wǎng)站嗎seo網(wǎng)絡(luò)排名優(yōu)化技巧
  • 網(wǎng)站建設(shè)的技術(shù)方案模板下載做app推廣去哪找商家
  • 給網(wǎng)站怎么做tag標(biāo)簽他達(dá)拉非片多少錢一盒
  • 地方電商門戶網(wǎng)站如何建設(shè)公司網(wǎng)站制作需要多少錢
  • 玄武模板網(wǎng)站制作報(bào)價(jià)怎么聯(lián)系百度推廣
  • 深圳外貿(mào)網(wǎng)站開發(fā)建設(shè)網(wǎng)絡(luò)營(yíng)銷出來可以干什么工作
  • 做動(dòng)態(tài)網(wǎng)站有哪些平臺(tái)關(guān)于市場(chǎng)營(yíng)銷的100個(gè)問題
  • 網(wǎng)站管理的內(nèi)容網(wǎng)站推廣系統(tǒng)
  • wordpress加授權(quán)網(wǎng)絡(luò)優(yōu)化工程師證書