功能相似於jQuery.ajax
。css
axios.post() axios.get() axios.put() axios.patch() axios.delete()
jQuery.ajax
功能更多ajax操做使用axios,dom操做使用vue,今後能夠不使用jqueryhtml
使用axios模擬後臺請求與響應就是Mock,也有專門的Moc庫例如:
http://mockjs.com/前端
生成隨機數據,攔截 Ajax 請求vue
要求從後臺獲取數據,初始化書的數量。加減書的時候也發送請求與響應,同時更新後臺數據。jquery
演示地址:
https://jsbin.com/jipewutagi/...ios
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>使用axios和jQuery完成簡單的先後臺交互(請求與響應)</title> <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> </head> <body> <div id='app'> <div> 書的名稱:《__name__》 <br> 書的數量:<span id='number'>__number__</span> </div> <button id='addOne'>加一</button> <button id='minusOne'>減一</button> <button id='reset'>歸零</button> </div> </body> </html>
let book = { name:'JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){//若是,就把初始book的數據響應過來 response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data)//先把拿到的請求轉化爲對象 Object.assign(book,dataObj) // Object.assign這個函數的做用是局部更新對象,把接收到的請求(book)裏面的number局部更新 console.log(book) response.data = book ;//局部更新後,再次賦值給響應,在這裏略過存儲數據庫,由於這只是假的後臺 } return response; }) // -------------上面是假的後臺----------------- // 先聲明好變量(有時候變量不能固定,好比更新了html的代碼後,這個變量就是舊的,就得從新取) let $app = $('#app') // let $number = $('#number') // let $addOne = $('#addOne') // let $minusOne = $('#minusOne') // let $reset = $("#reset") // 請求初始值 axios.get('/book/1') .then(({data})=>{//獲取響應成功後更新html的代碼 // 這裏使用的是es6語法,其實是let data = response.data let originalHtml = $app.html() let newHtml = originalHtml.replace('__name__',data.name).replace('__number__', data.number) $app.html(newHtml) }) // 進行加一個的請求 $app.on('click', '#addOne', function(){//事件委託,點擊app上的addone的時候,將點擊事件委託給addone let newNumber = $('#number').text()-0+1 let book = { number:newNumber } axios.put('/book/1', book) .then(({data})=>{ $('#number').text(data.number)//接收到響應以後在更新前端代碼 }) }) //下面減一和重置同理 $app.on('click', '#minusOne', function(){//事件委託,點擊app上的addone的時候,將點擊事件委託給addone let newNumber = $('#number').text()-0-1 let book = { number:newNumber } axios.put('/book/1', book) .then(({data})=>{ $('#number').text(data.number)//接收到響應以後在更新前端代碼 }) }) $app.on('click', '#reset', function(){//事件委託,點擊app上的addone的時候,將點擊事件委託給addone let newNumber = 0 let book = { number:newNumber } axios.put('/book/1', book) .then(({data})=>{ $('#number').text(data.number)//接收到響應以後在更新前端代碼 }) })
事件委託:點擊父元素,若是同時點到了子元素就把事件委託給他。
經過事件委託,監聽app的點擊事件,若是點的是委託的子元素,就執行監聽的函數程序員
上面的代碼很亂。es6
上面的代碼很亂。使用MVC模式重構代碼,把代碼分紅視圖,數據,控制數據和視圖三塊,分別用一個對象表示,下面是過程ajax
演示代碼
https://jsbin.com/ceyukirube/...數據庫
fakeData() // -------------上面是假的後臺----------------- let model = { data:{ name:'', number:0, id:'' }, fetch:function (id){ return axios.get(`/book/${id}`).then((response)=>{ this.data = response.data return response }) }, update:function(id,data){ return axios.put(`/book/${id}`,data).then((response)=>{ this.data = response.data return response }) } } let $app = $('#app') model.fetch(1).then(({data})=>{//這裏把操做數據的方法寫在了model裏 let originalHtml = $app.html() let newHtml = originalHtml.replace('__name__',data.name).replace('__number__', data.number) $app.html(newHtml) }) $app.on('click', '#addOne', function(){ let newNumber = $('#number').text()-0+1 let book = { number:newNumber } model.update(1,book).then(({data})=>{//這裏把操做數據的方法寫在了model裏 $('#number').text(data.number) }) }) $app.on('click', '#minusOne', function(){ let newNumber = $('#number').text()-0-1 let book = { number:newNumber } model.update(1,book) .then(({data})=>{ $('#number').text(data.number) }) }) $app.on('click', '#reset', function(){ let newNumber = 0 let book = { number:newNumber } model.update(1,book) .then(({data})=>{ $('#number').text(data.number) }) }) function fakeData(){//假的後臺 let book = { name:'JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){ response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data) Object.assign(book,dataObj) console.log(book) response.data = book ; } return response; }) }
演示地址
https://jsbin.com/fakegurono/...
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>使用axios和jQuery完成簡單的先後臺交互(請求與響應)</title> <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> </head> <body> <div id='app'> </div> </body> </html>
fakeData() // -------------上面是假的後臺----------------- let model = { data:{ name:'', number:0, id:'' }, fetch:function (id){ return axios.get(`/book/${id}`).then((response)=>{ this.data = response.data return response }) }, update:function(id,data){ return axios.put(`/book/${id}`,data).then((response)=>{ this.data = response.data return response }) } } let view = { el:'#app', template:`<div> 書的名稱:《__name__》 <br> 書的數量:<span id='number'>__number__</span> </div> <button id='addOne'>加一</button> <button id='minusOne'>減一</button> <button id='reset'>歸零</button> `, render(data){//渲染 let newhtml = this.template.replace('__name__',data.name).replace('__number__', data.number) $(this.el).html(newhtml) } } let $app = $('#app') model.fetch(1).then(({data})=>{//es6語法,response裏的data //這裏把操做數據的方法寫在了model裏 view.render(data) // 或者view.render(model.data)由於上面model在操縱數據的時候,獲取響應的時候,把data傳給了model.data,因此response.data 和model.data同樣,兩個均可以用 }) $app.on('click', '#addOne', function(){ let newNumber = $('#number').text()-0+1 let book = { number:newNumber } model.update(1,book). then(({data})=>{//這裏把操做數據的方法寫在了model裏 view.render(data) }) }) $app.on('click', '#minusOne', function(){ let newNumber = $('#number').text()-0-1 let book = { number:newNumber } model.update(1,book) .then(({data})=>{ view.render(data) }) }) $app.on('click', '#reset', function(){ let newNumber = 0 let book = { number:newNumber } model.update(1,book) .then(({data})=>{ view.render(data) }) }) //假的後臺,不要看 function fakeData(){//假的後臺 let book = { name:'JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){ response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data) Object.assign(book,dataObj) console.log(book) response.data = book ; } return response; }) }
代碼開始變得條理清晰
把操縱model和view的操做封裝成controller 對象
演示地址:
https://jsbin.com/sezuquxuko/...
fakeData() // -------------上面是假的後臺----------------- let model = { data:{ name:'', number:0, id:'' }, fetch:function (id){ return axios.get(`/book/${id}`).then((response)=>{ this.data = response.data return response }) }, update:function(id,data){ return axios.put(`/book/${id}`,data).then((response)=>{ this.data = response.data return response }) } } let view = { el:'#app', template:`<div> 書的名稱:《__name__》 <br> 書的數量:<span id='number'>__number__</span> </div> <button id='addOne'>加一</button> <button id='minusOne'>減一</button> <button id='reset'>歸零</button> `, render(data){//渲染 let newhtml = this.template.replace('__name__',data.name).replace('__number__', data.number) $(this.el).html(newhtml) } } let controller = { init:function(options){ this.view = options.view this.model = options.model this.view.render(this.model.data) this.bindEvents() this.model.fetch(1).then(({data})=>{ this.view.render(data) }) }, bindEvents:function(){ //到這一層,this還指的是controller這個對象,可是到點擊事件那一層,addOne函數裏,this表明點擊的那個元素(jQuery規定的)。 // 因此要使用addOne.bind(this)把controller這一層的this綁定到addOne那更深刻的一層去,使this同一爲controller這個對象 $(this.view.el).on('click', '#addOne', this.addOne.bind(this)) $(this.view.el).on('click', '#minusOne',this.minusOne.bind(this) ) $(this.view.el).on('click', '#reset', this.reset.bind(this)) }, addOne:function(){ let newNumber = $('#number').text()-0+1 let book = {number:newNumber} this.model.update(1,book).//這個this已經被bind爲controller then(({data})=>{ this.view.render(data)//這個this已經被bind爲controller }) }, minusOne:function(){ let newNumber = $('#number').text()-0-1 let book = { number:newNumber } this.model.update(1,book)//這個this已經被bind爲controller .then(({data})=>{ this.view.render(data) }) }, reset:function(){ let newNumber = 0 let book = { number:newNumber } this.model.update(1,book) .then(({data})=>{ this.view.render(data) }) } } controller.init({model:model,view:view})//初始化,並把Model和View傳進去 //假的後臺,不要看 function fakeData(){//假的後臺 let book = { name:'JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){ response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data) Object.assign(book,dataObj) console.log(book) response.data = book ; } return response; }) }
由於這個頁面的Model和View只是這個頁面特有的,假以下個頁面不是這個View和Model,那麼還須要從新重寫一遍代碼,因此要把把Model,View和controller抽象成類。這樣每有新的頁面中的一塊html須要操做,就new一個對象便可。通常來講MVC作成一個庫,而後去引用他就行了
先寫構造函數,而後把公有屬性寫在prototype裏,最後new就能夠了。
演示地址:
https://jsbin.com/mifameqona/...
controller類暫時不寫
fakeData() // -------------上面是假的後臺----------------- //從這開始寫MVC類 function Model(options){//這裏面寫特有的屬性 this.data = options.data this.resource = options.resource//把請求的地址也寫成特有的屬性 } Model.prototype.fetch = function(id){//共有屬性 return axios.get(`/${this.resource}/${id}`).then((response)=>{ this.data = response.data return response }) } Model.prototype.update = function(id,data){ return axios.put(`/${this.resource}/${id}`,data).then((response)=>{ this.data = response.data return response }) } function View(options){ this.el = options.el; this.template = options.template; } View.prototype.render = function(data){ var newhtml = this.template for(let key in data){ newhtml = newhtml.replace(`__${key}__`,data[key])//用循環替換data裏面的字符串 } $(this.el).html(newhtml) } // --------上面是MVC類----------- //使用MVC類新生成的對象 let bookModel = new Model({data:{name:'',number:0,id:''},resource:'book'}) let bookView = new View({ el:'#app', template:`<div> 書的名稱:《__name__》 <br> 書的數量:<span id='number'>__number__</span> </div> <button id='addOne'>加一</button> <button id='minusOne'>減一</button> <button id='reset'>歸零</button> ` }) let controller = { init:function(options){ this.view = options.view this.model = options.model this.view.render(this.model.data) this.bindEvents() this.model.fetch(1).then(({data})=>{ this.view.render(data) }) }, bindEvents:function(){ //到這一層,this還指的是controller這個對象,可是到點擊事件那一層,addOne函數裏,this表明點擊的那個元素(jQuery規定的)。 // 因此要使用addOne.bind(this)把controller這一層的this綁定到addOne那更深刻的一層去,使this同一爲controller這個對象 $(this.view.el).on('click', '#addOne', this.addOne.bind(this)) $(this.view.el).on('click', '#minusOne',this.minusOne.bind(this) ) $(this.view.el).on('click', '#reset', this.reset.bind(this)) }, addOne:function(){ let newNumber = $('#number').text()-0+1 let book = {number:newNumber} this.model.update(1,book).//這個this已經被bind爲controller then(({data})=>{ this.view.render(data)//這個this已經被bind爲controller }) }, minusOne:function(){ let newNumber = $('#number').text()-0-1 let book = { number:newNumber } this.model.update(1,book)//這個this已經被bind爲controller .then(({data})=>{ this.view.render(data) }) }, reset:function(){ let newNumber = 0 let book = { number:newNumber } this.model.update(1,book) .then(({data})=>{ this.view.render(data) }) } } controller.init({model:bookModel,view:bookView})//初始化,並把Model和View傳進去 //假的後臺,不要看 function fakeData(){//假的後臺 let book = { name:'JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){ response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data) Object.assign(book,dataObj) console.log(book) response.data = book ; } return response; }) }
在前端開始慢慢發展的時候,前端程序員就是這樣進行技術迭代的,上面就是MVC迭代的過程。這就是MVVM出現以前的MVC。
從上面的代碼來看,view類的做用是:
VUE框架的做用是能夠把MVC裏的view類使用VUE代替。
注意:
從傳統MVC轉到VUE的MVC就是忘掉render,把data放到vue上面,要更新數據,就直接更新vue裏面的data便可。
把render變成了簡單的賦值操做。並且這種渲染只更新你改變的那個值所在的節點,不會渲染所有模板。
vue第一個特色是data歸他管,第二就是會精細得更新該渲染的地方。
但vue的野心不只於此,vue可讓你作到不須要controller。由於controller最重要的功能綁定事件,vue有一種語法能夠綁定事件。具體用法是在html屬性裏添加v-on:click="f",而後在methods 裏寫f函數便可。
代碼
演示地址:
https://jsbin.com/bocecuxaya/...
主要代碼:
fakeData() // -------------上面是假的後臺----------------- //從這開始寫MVC類 function Model(options){ this.data = options.data this.resource = options.resource } Model.prototype.fetch = function(id){ return axios.get(`/${this.resource}/${id}`).then((response)=>{ this.data = response.data return response }) } Model.prototype.update = function(id,data){ return axios.put(`/${this.resource}/${id}`,data).then((response)=>{ this.data = response.data return response }) } // --------上面是Model類----------- let bookModel = new Model({data:{name:'',number:0,id:''},resource:'book'}) let bookView = new Vue({//不用寫view類了,直接用vue充當view類,須要傳入data, el:'#app', data:{//data裏的屬性會轉變爲vue對象的屬性 book:{ name:'', number:0, id:'1' }, n:1//兩個數據,一個book對象,一個n的值 }, //template只能有一個根元素 template:` <div> <div> 書的名稱:《{{book.name}}》 <br> 書的數量:<span id='number'>{{book.number}}</span> </div><br><br> 雙向綁定:<br> 輸入須要加或者減的數:<input type='text' v-model='n'><br> n的值爲<span>{{n}}</span><br><br><br> <button v-on:click='addOne'>加n</button> <button v-on:click='minusOne'>減n</button> <button v-on:click='reset'>歸零</button> </div> `, created:function(){//在創造vue時執行的函數,進行首次渲染 bookModel.fetch(1).then(({data})=>{ //vue會直接同步渲染html,因此直接賦值給view.name和number就行了 this.book = bookModel.data;//或者this.book = data;由於data是傳回來的response,在model裏,也把傳回來的數據放到了model裏 // this.view.render(this.model.data)這句不須要了,由於修改vue數據後會自動渲染 }) }, methods:{//綁定的事件的函數 addOne:function(){ let newNumber = this.book.number + (this.n-0)//+n //直接獲取內存裏的number,由於內存和頁面是統一的,不須要獲取dom了 let book = {number:newNumber} bookModel.update(1,book).//直接用聲明的bookModel對象裏面的update方法,由於沒有controller了 then(({data})=>{ // this.view.render(data) this.book = data//返回的數據直接賦值給book,便可渲染 }) }, minusOne:function(){ let newNumber = this.book.number - (this.n-0)//-n let book = { number:newNumber } bookModel.update(1,book) .then(({data})=>{ // this.view.render(data) this.book = data }) }, reset:function(){ let newNumber = 0 let book = { number:newNumber } bookModel.update(1,book) .then(({data})=>{ // this.view.render(data) this.book = data }) } } }) //假的後臺,不要看 function fakeData(){//假的後臺 let book = { name:'我是初始名稱JavaScriptBook', number:10, id:'1' } // 在response真正返回以前攔截,修改他的數據,使用這個api來模擬後臺響應數據 axios.interceptors.response.use(function(response){ let {config: {url, method, data}} = response // ES6語法,從response裏的config拿出url method data,並聲明 if(url === '/book/1' && method === 'get'){ response.data = book } else if(url === '/book/1' && method === 'put'){ let dataObj = JSON.parse(data) Object.assign(book,dataObj) console.log(book) response.data = book ; } return response; }) }
可是vue無論model層的事
vue作的事就是讓mvc裏的v更智能,且能合併mvc的c
渲染是一種單向綁定,只單向得改變html的值。
vue就是自動化的mvc,既MVVM
經過以上的分析,咱們發現,咱們不須要去綁定事件,也不須要去render了,我須要作的就是取值和賦值。
什麼是MVVM:
https://juejin.im/entry/59996...
Vue 浮層例子:http://jsbin.com/nabugot/1/ed...
Vue 輪播例子:https://jsbin.com/kerabibico/...
Vue tab切換例子:http://jsbin.com/hijawuv/1/ed...