項目上使用 axios 的攔截器是在 jsbin.com 中進行的,同時要把jsbin的JavaScript改成es6 若是你在本地實驗會發現攔截器不起做用,這是正常的。 你若是想讓本地的攔截器也起做用,就須要本身寫 server.js 來響應全部請求javascript
axios是ajax的庫css
如何用 axios GET 請求 /xxx?id=1html
1.axios.get('/xxx?id=1')
2.axios.get('/xxx', {id:1})
3.axios.get('/xxx', {params: {id:1}} )
4.axios({method:'get', url: '/xxx?id=1'})
5.axios('/xxx?id=1');
複製代碼
之前咱們使用ajax能夠這麼用:前端
1.$.ajax({
url: '/xxx'
method: 'post'
})
2.$.post('/xxx',data)
3.$.gat('/xxx')
複製代碼
使用axios的用法:vue
1.axios.post()
2.axios.get()
3.axios.put()
4.axios.patch()
5.axios.deleate()
複製代碼
1.比 jQuery.ajax功能更多java
2.除了ajax功能以外,沒有其餘功能(更專一)node
有了替代品以後jQuery就能夠死掉了ios
第一個版本es6
爲何減0,是把字符串轉成numberajax
interceptors是攔截機,意思就是往...裏面植入一個東西或者攔截一個東西
在真正返回response以前使用一個函數,這個函數會對response作一個修改
不作服務器,直接把前端的數據寫死,也就是mock
咱們有沒有辦法根據請求的URl來mock不一樣的數據呢?能夠,咱們去獲取一下這個response的config就好了,config裏面有一個重要的屬性url,method和data注意這裏的data是請求data,這裏的if ...else... 仍是和nodejs很像的,像nodejs的路由
let config = response.config
let {method,url,data} = config
複製代碼
上面的2行能夠用es6的解構語法把它們合併成一行,這樣咱們就同時獲得了4個變量分別是config,method,url,data
let {config:{method,url,data}} = response
複製代碼
如今咱們就能夠去僞造數據,response.data返回的就是咱們須要的數據,html中的書名和數量不能寫死,要從response.data裏去取
怎樣把響應的數據塞到get的Promise的成功回到裏呢?
能夠: let data = response.data
,可是用es6的語法就是回調的參數{data},就能夠拿到data了,log這個data
接着就是把這個data的數據弄到html中app裏面
axios.get('/book/javascript').then(({data})=>{
let oldHtml = $('#app').html()
let newHtml = oldHtml.replace('__name__',data.name).replace('__number__',data.number)
$('#app').html(newHtml)
})
複製代碼
這時候會發現,點擊加1按鈕不行了,爲何由於以前的html被更改了,因此要作一下事件委託
由以前的
$('#addOne').on('click',function(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber + 1
$('#number').text(newNumber)
})
$('#minusOne').on('click',function(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber - 1
$('#number').text(newNumber)
})
$('#reset').on('click',function(){
var oldNumber = $('#number').text() -0
var newNumber = 0
$('#number').text(newNumber)
})
複製代碼
改成:
$('#app').on('click','#addOne',function(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber + 1
$('#number').text(newNumber)
})
$('#app').on('click','#minusOne',function(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber - 1
$('#number').text(newNumber)
})
$('#app').on('click','#reset',function(){
var oldNumber = $('#number').text() -0
console.log(oldNumber)
var newNumber = 0
$('#number').text(newNumber)
})
複製代碼
它的意思就是在點擊#app裏面的任何一個元素的時候,只要這個元素元素符合"#addOne"(或其餘)就會觸發事件
上面作的內容爲:用ajax發請求,再用ajax獲取到數據,而後再將數據替換到頁面中的
$('#app').on('click','#addOne',function(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber + 1
axios.put('/book/javascript',{ // 加上的東西
number: newNumber
})
$('#number').text(newNumber)
})
複製代碼
也就是說,先把{number: newNumer}數據push到服務器,若是push成功了,再改頁面上的數據
假的服務器axios同時也要對put的作出響應,當請求的url是'/book/javascript'而且method爲get的時候說明是想要獲取舊的數據,就response舊的數據;當請求的路徑是'/book/javascript'而且method是put的時候,確定要push一個新的數據,因而響應就要修改舊的數據,這個數據就是書的數量,全部要要有個書的變量,而且設置初始狀態
assign的語法就是部分更新,asssgn就是批量的賦值,同時assign能夠進行屢次賦值,後面的會覆蓋前面的
回到代碼中理解assign,傳的是什麼data(data是請求的data),assign就會把data覆蓋到book上,同時book會存住數據的變化,而後把data做爲數據(book上的數據)經過book返回給你,注意這裏的data是字符串,要轉成對象
let data = JSON.parse(data)
Object.assign(book,data); // 請求的data
response.data = book // 響應的data
複製代碼
這時候點擊按鈕加1,控制檯就會發送一個put請求
這樣基本的功能就實現了,可是代碼存在一個問題,就是是意大利麪條式代碼,代碼邏輯結構不清晰
首先要把以前假的服務器的那一塊包裝成一個函數叫fakeData
所謂MVC就是把代碼分割成3快功能職責劃分明確的代碼
首先改MVC的Model
聲明一個model的對象,用來處理和數據相關的操做,model裏面要有一個獲取數據的函數fetch,一旦獲取數據成功就把數據存到model上,記住要return這個response,只有return了,後面才能接着then.也要有一個更新數據的函數updata,它也和fetch同樣一旦put成功就會返回一個Promise,成功了就調成功的回調 那咱們的數據存在哪裏呢?因此model上還得有一個叫data的屬性,用來放數據的初始值
而後就不要去管怎麼去獲取說數據了
axios.get('/book/javascript') => .then(({data})=>{
複製代碼
改成:
model.fetch('javascript')
複製代碼
也不用去管怎麼去更新數據了
axios.put('/book/javascript',{
number: newNumber
})
複製代碼
改成:
model.update({number: newNumber })
複製代碼
它返回的是一個Promise對象,能夠繼續then,
model.update({number: newNumber })
$('#number').text(newNumber)
複製代碼
改成:
model.update({number: newNumber }).then(()=>{
$('#number').text(newNumber)
})
複製代碼
接下來去改MVC的View
全部和html相關的操做交給view來作,操做的元素是什麼el,內容是什麼,一開始內容是寫在html裏面,其實應該交給view來初始化,做爲view的字符串模板
何時去作初始化呢?render(data)函數會去找到template而且把它裏面的佔位符替換爲model傳來的data,渲染頁面的時候會從model那裏獲得這個data
let view = {
el: "#app",
template: `
<div>
書名: __name__
數量: <span id = "number">__number__</span>
</div>
<div>
<button id = "addOne">加1</button>
<button id = "minusOne">減1</button>
<button id = "reset">置0</button>
</div>
`,
render(){
let html = this.template.replace('__name__',data.name).replace('__number__',data.number)
$(this.el),html(html)
}
}
複製代碼
這樣以前舊的代碼:
let newHtml = oldHtml.replace('__name__',data.name).replace('__number__',data.number).replace('__name__',data.name)
$('#app').html(newHtml)
複製代碼
就能夠被替換爲:
let oldHtml = $('#app').html()
複製代碼
更新view的代碼:
$('#number').text(newNumber)
複製代碼
也改成:
view.render(data)
複製代碼
那麼這個data哪裏來的?
咱們能夠從更新的成功回調裏面去取.這個data = response.data
model.update({number: newNumber }).then(({data})=>{
view.render(data)
})
複製代碼
也能夠從model上去取:
由於model把response.data記到本身的data上了
let model = {
+++
update(data){
let id = this.data.id
return axios.put(`/book/{id}`,data).then((response)=>{
this.data = response.data
return response
})
+++
複製代碼
因此把全部的
view.render(data) => view.render(model.data)
複製代碼
回顧一下:
model會去獲取一個數據,在返回數據以前,它會把response.data記到本身的data上;更新也是,返回更新的數據以前會把response.data記到本身的data上
view接收一個data,而後就把模板字符串更新渲染到#app裏面
model會去獲取叫javascript的書獲取成功後,就把它的數據給view渲染一下
接下來再寫controller
view和model以外的東西都交給controller來作,分爲初始化和事件綁定bindEvents,bindEvents就是對view的元素進行事件綁定
(this.view.el)`
把3個對按鈕的事件,封裝成函數放在controller上
日常經過log(數字),二分法排bug
bindEvents(){
// 外面的this是controller
$(this.view.el).on('click','#addOne',this.addOne) // 這裏的this是什麼
$(this.view.el).on('click','#minusOne',this.minusOne)
$(this.view.el).on('click','#reset',this.reset)
}
複製代碼
外面的this是controller若是想要它裏面的this也是controller就得用bind()綁定,這樣就能保證每個this表明controller
bindEvents(){
$(this.view.el).on('click','#addOne',this.addOne.bind(this) // 這裏的this是被點擊的元素,最好看一下jQ的on事件的click的this是什麼
$(this.view.el).on('click','#minusOne',this.minusOne.bind(this))
$(this.view.el).on('click','#reset',this.reset.bind(this))
}
複製代碼
對第二個版本繼續迭代,若是實際中有不少頁面,那麼每一個也頁面都要寫一次M,V,C這3個對象,而後,每次寫對象都要寫不少重複的代碼是否是很麻煩?
那如何解決這個問題呢?
咱們應該把共同的屬性寫到一個class裏面或者構造函數,把共用的代碼寫到它的原型上面(要知道哪些是須要傳的參數),特有屬性放到它的構造函數裏面,可是是經過傳參的形式
例子中的model的data是屬於特有的屬性,因此要放到它構造函數的裏面,而fetch和update是公寓屬性得放到model的構造函數Model的共有屬性上
請求的路徑的book也能夠不用寫死,而是能夠去從參數那裏獲取
這樣寫的好處就是:
咱們每次使用Model的代碼就能夠簡化成只要寫2個屬性,而且還能夠造一個關於車的Model等
let bookModel = new Model({
data:{
name: '',
id : '',
number: 0
},
resource: 'book'
})
booModel.fetch('javascript')
let carModel = new Model({
data: {
...
}
resource: 'car'
})
複製代碼
再構造一個View的構造函數出來:
每個view的el是不同的,每個view的template也是不同的,只有render是共有屬性放到View的原型上,el和template做爲私有屬性應該放到View的構造函數上
template的__name__和__number__也不能寫死,得去遍歷data
View.prototype.render = function(data){
let html = this.template
for(let key in data){
html = html.replace(`__${key}__`,data[key])
}
$(this.el).html(html)
}
複製代碼
把View的el和templat綁定到它的this上
function View({el,template}){
this.el = el
this.template = template
}
複製代碼
以便於後面使用
View.prototype.render = function(data){
let html = this.template
for(let key in data){
html = html.replace(`__${key}__`,data[key])
}
$(this.el).html(html)
}
複製代碼
注意: this.xxx = xxx是一個很是重要的操做,一旦忘了記,就會報undefined
先去bootcdn上引入vue的cdn到頁面上
而後把以前構造的View刪除,而後把new view 改成new vue,這樣基本就能夠了
可是語法得改一下
1.把__name__改成{{name}}也就是說vue的作標記會不同
2.這個new出來的view會強制讓把data傳給它,不要傳給model,它須要這個data,這個view須要根據這個data去初始化template
3.template只能有一個根元素,若是有2個,那麼vue只會看第一個,也就是說最外面只需套一個div
vue就是把MVC作一下升級,只要把MVC搞清楚了,Vue的原理就搞清楚了
4.那render怎麼辦?沒有render了,vue會有一個自動render的機制,以前寫的MVC在controller中view會render數據data,引入Vue以後就不須要render了,由於data已經放到vue上了,初始化vue會幫咱們作
5.那當咱們獲取到數據以後怎麼去更新view呢?vue是沒有render函數的,按道理說應該去改view的data
以前的
this.view.render(this.model.data)
複製代碼
是否是這樣改?
this.view.data = this.model.data
複製代碼
6.Vue的一個重要特色,view會把data的屬性升級到當前的view實例上面,也就是說有原來的view.data.name升級到了view.name,view.data.id升級到了view.name,view.data.number升級到了view.number 也就是說不是改view.data仍是直接去改view
this.model.fetch('javascript').then(()=>{
this.view.name = this.model.data.name
this.view.id = this.model.data.id
this.view.number= this.model.data.number
})
複製代碼
也就是說一旦改動了view上的data的name,id,number,那麼html就會自變,不用管render,vue會自動render
到目前爲止引入vue以後和以前的MVC比較變化就是:
1>.忘掉render
2>.把data放到view上
3>.咱們須要改什麼只要改data就好了
上面的寫法感受比較麻煩有簡潔一點的寫法嗎?
有
let view = new Vue({
el: "#app",
data:{
book:{
name: '未命名',
number: 0,
id: ''
}
},
+++
複製代碼
這樣寫vue會把book當作view的屬性而不是view.data的屬性
this.model.fetch('javascript').then(()=>{
this.view.book = this.model.data
})
複製代碼
注意:改了以後記得改模板字符換裏面的變量的層級從屬關係
let view = new Vue({
el: "#app",
data:{
book:{
name: '未命名',
number: 0,
id: ''
}
},
template: `
<div>
<div>
書名: 《{{book.name}}》
數量: <span id = "number">{{book.number}}</span>
</div>
<div>
<button id = "addOne">加1</button>
<button id = "minusOne">減1</button>
<button id = "reset">置0</button>
</div>
</div>
`
})
複製代碼
vue把同步html這件事情變得很簡單了,使得咱們把注意力從關注dom中抽離出來,vue會負責去拿到數據而後去渲染頁面,使得咱們只須要去關注獲取數據更改數據就好了,其餘的事情交給vue就能夠了
並且vue很厲害的地方就是vue不會刷新整個html,它只改該改的地方,能夠作到拿到數據變化,只局部更新數據變化對應頁面,而後局部渲染頁面.做爲對比,以前用MVC寫的頁面會從新更新所有的html
7.Vue的野心不止於此,Vue甚至可讓咱們作到不須要controller,controller最重要的一件事就是綁定事件,若是Vue有一種語法能夠更方便的綁定事件呢? 把以前放在controller上全部的工具函數,放到view的methods屬性裏面
那當用戶點擊按鈕的時候怎麼觸發view裏面的methods裏面的addOne函數,minusOne函數, reset()函數呢?Vue有它本身的綁定事件的語法:
<button id = "addOne" v-on:click="addOne">加1</button>
複製代碼
意思就是當用戶點擊這個按鈕的時候就觸發addOne函數,id也沒用了!已經不須要選擇元素了,直接在元素上就完成了事件綁定
修改完就是:
<div>
<div>
書名: 《{{book.name}}》
數量: <span id = "number">{{book.number}}</span>
</div>
<div>
<button v-on:click="addOne">加1</button>
<button v-on:click="minusOne">減1</button>
<button v-on:click="reset">置0</button>
</div>
</div>
複製代碼
也不必用jQ去獲取text了,直接去改view,讓this.data.book.number + 1 ,可是Vue的語法不是這樣的 vue會把data上的屬性偷偷的放到本身身上,就變成了this.book.number + 1
methods: {
addOne(){
var oldNumber = $('#number').text() -0
var newNumber = oldNumber + 1
this.model.update({number: newNumber }).then(()=>{
this.view.render(this.model.data)
})
}
複製代碼
==>
methods: {
addOne(){
model.update({number: this.book.number + 1}).then(()=>{
this.view.book = this.model.data
})
}```,
minusOne(){
this.model.update({number: this.book.number - 1 }).then(()=>{
this.view.book = this.model.data
})
},
reset(){
this.model.update({number: this.book.number - 1}).then(()=>{
this.view.book = this.model.data
})
}
}
複製代碼
注意:
i.這裏的this.book.就是this.data.book,Vue會把data裏面的屬性偷偷的放到本身身上
ii.model前不須要加this,由於Vue是無論model層的它不想操這個心,這個model是外面的model,是變量model不是屬性model,因此把this刪掉,直接用model這個變量,model仍是以前的MVC的model,可是controller被合併了,view被語法糖了
iii.更新數據成功後,也不須要rendel,只須要修改data上的數據就好了
iv.發現vue好像一直在作的事情就是更新model而後從Model那裏拿數據,沒有DOM
v.Vue的文檔給了咱們第一步初始化的操做,在view裏面加一個方法,created(){},通常能夠在created函數中調用ajax獲取頁面初始化所需的數據
created(){
model.fetch('javascript').then(()=>{
this.book = model.data
})
}
複製代碼
model.fetch('javascript')就是發起get請求,服務器給予響應,響應的內容爲data,而後就把數據賦給view的book.name變成新的number,name變成新的name,id變成新的id,而後Vue就會自動更新頁面.
當點擊加1的時候,已經綁定了事件爲addOne,因此就會自動調用addOne,addOne會讓model去updata,而後會獲得新的數據data,而後把這個新的數據給view的book
這樣就只須要作賦值和取值,就好了.有新的數據就賦值給book,想取book的值時候就this.book.numbe.如:
addOne(){
model.update({number: this.book.number+1 }).then(()=>{ //想取book的時候
this.view.book = this.model.data // 有新的數據就賦值給book
})
複製代碼
Vue的好處就是讓以前的vue變得更智能(能夠自動render),同時MVC的C能夠合併到Vue裏面(methods放工具函數,created方法用來調用ajax獲取頁面初始化所需的數據)
咱們不加1減1,而是加n減n
咱們須要一個n放到data上面
把n放到頁面的input上,通常用v-model
把methods裏面的1改成this.n(字符串須要減0)
當咱們在輸入框中輸入5的時候,n的值會立刻變成5,這就是雙向綁定
以前並無用戶的輸入,只要渲染出來就好了,渲染只是一種單向綁定
註釋:
一開始是1很好理解.直接根據data去渲染就好了
當咱們在輸入框中輸入5的時候,首先Vue會發現n變了,因而就把data的屬性n變成5.n變成5以後Vue發現 n的值是:{{n}}這裏的n也得變,因而就變了
從圖中看出:
單向綁定: 若是隻是從內存到頁面的render的過程就是單向綁定
雙向綁定: 若是render以後,當用戶改輸入框中的值的時候,還能反着映射到內存.那麼這就是雙向綁定
Vue屬於自動化的MVC(不須要view.render(model.data)Vue會自動幫咱們render)
1.由於Vue把MVC的controllerg改成 ==> 放到它的methods屬性裏面(M) 2.同時把以前的MVC的初始化controller(就是把view和model當參數傳給controller)改成 ==> 放到它的created方法裏面(C)
因此Vue就是一個從MVC到MVVM的過程
axios代替了ajax,vue代替了dom先關的操做,因此jQ就...
用框架顯示做者牛x,用原生js顯示本身牛x
用了vue就不要去碰dom
第一個小組件: Popover 組件
第二個小組件: Slides 組件
v-on:click="go(x)" 不只支持加函數名錶示執行函數還支持函數名加參數的形式
v-bind:style = ""表示在div上綁定一個style屬性
v-on表示事件監聽; v-bind表示綁定
Vue的調試不能用控制檯調試須要用html調試,如: {transformValue}
第三個小組件: Tab組件
變複雜了,同時變容易了。複雜的反義詞是簡單。 容易的反義詞是困難。電鋸很複雜,可是用電鋸砍樹很容易。斧頭很簡單,可是用斧頭砍樹很困難。若是電鋸壞了,你就哭吧。由於修電鋸太複雜了。 若是斧頭壞了,磨一磨斧刃或者換根柄就行了。由於斧頭簡單。若是你只須要砍幾棵樹,買個電鋸是否是划不來?電鋸還須要用電,你砍樹的地方首先得有電你才能用電鋸,否則你就得柴油發電了。對普通人家來講,仍是常備斧子吧。通常來講複雜的東西會有一堆須要記的東西(寫在電鋸的說明書上)你看 Vue、React、Angular 的說明書有多厚就知道了。而簡單的東西則記住一些簡單的規則就好了:好比不要用斧頭砍本身或其餘人。你喜歡容易,仍是簡單?大部分人喜歡複雜而容易的東西。
會用Vue不能說明咱們牛X,只能說Vue的做者牛X
若是隻是作很簡單的事情,買電鋸是划不來的,學習Vue的過程就是買電鋸,學習Vue的過程是須要好久的,如今才能大概理解Vue就是MVC的升級版,MVC的M要作ajax,MVC的V是操做頁面的DOm樹,C是控制流程的學習了算法數據結構和jS的基本語法,這樣才能勉強算理解Vue,理解Vue的過程就是買電鋸的花費,就是學習瞭解Vue須要掌握的基礎知識包括ES6語法
大部分人喜歡複雜而容易的東西。好比你很喜歡開車,掌握方向盤和油門剎車就能夠去想去的地方,可是若是讓你去了解汽車的構造原理,瞭解爲何打方向盤車就會轉彎,掛擋踩油門車爲何就有動力等就會變得特別複雜,跟不想學
學基礎就是爲了能瞭解MVC,之後學習其餘框架同樣要用到MVC的知識,MVC的M同樣會用到ajax,MVC的V同樣會用到DOM,MVC的C同樣會用到數據結構,算法以及面向對象的知識