说说axios和mvc

首先Vue里面用到了mvc,那么要理解Vue就要先从mvc讲起
接下来我们通过写一个图书信息展示来理解
html




  
  
  
  JS Bin


  
书名:"JavaScript高级程序设计" 数量:2

js

$("#app").on("click","#add",function(){
  var oldNumber=$("#number").text()
  var newNumber = oldNumber-0+1
  $("#number").text(newNumber)
})

$("#app").on("click","#minus",function(){
  var oldNumber=$("#number").text()
  var newNumber = oldNumber-0-1
  $("#number").text(newNumber)
})

$("#app").on("click","#reset",function(){
  var newNumber = 0
  $("#number").text(newNumber)
})

上面的代码是直接把数据写进页面里的,我们可以发一个请求来得到这个数据再写到页面里,这里我们引入axios来请求数据,并在真正返回response之前用axios的拦截机拦截一下,然后修改response之后再返回response

axios.interceptors.response.use(function(response){
    let {url,method,data}=response.config
    if(url === '/books/1' && method === 'get'){
      response.data = {
        name:'JavaScript高级程序设计',
        number:2,
        id:1
      }
    }
  return response
})

axios.get('/books/1').then((response)=>{
  let{data} = response
  let originalHtml = $('#app').html()
  let newHtml = originalHtml.replace('__name__',data.name)
  .replace('__number__',data.number)
  $('#app').html(newHtml)
})

这里先用axios发一个get请求,然后拦截机里的response.config可以拿到请求的url,method,data,如果请求的url是“/books/1”而且方法是get那么就返回数据,同时原始html里的number,name用__name____number__代替。当请求成功拿到response之后,拿到里面的data,然后把data里面的name和number的值替换之前的__name____number__
然后每次点击按钮,能不能也发一个put请求,然后通过响应再改数值,还是用axios来put请求

$("#app").on("click","#add",function(){
  var oldNumber=$("#number").text()
  var newNumber = oldNumber-0+1
  axios.put('/books/1',{number:newNumber}).then(()=>{
     $("#number").text(newNumber)
  })
})
var book={
  name:'JavaScript高级程序设计',
  number:2,
  id:1
}
axios.interceptors.response.use(function(response){
    let {url,method,data}=response.config
    if(url === '/books/1' && method === 'get'){
      response.data = book
    }else if(url === '/books/1' && method === 'put'){
      data = JSON.parse(data)
      Object.assign(book,data)
      console.log(book)
      response.data = book
    }
  return response
})

把newNumber当做data一起请求过去,然后为这个put做一个路由,当url和method都满足后,先把请求的data变成对象,然后用Object.assign这个api把book里面的number替换掉,再返回这个book。
到这里我们已经完成了一个人“意大利面条式代码”,长短交错看起来很乱,而且数据视图还有逻辑都是想到哪里写哪里,这就有了引入mvc的需求。
“m”就是“model”负责数据,
“v”就是view负责页面样式,
“c”就是controller负责逻辑,

let model={
  data:{
    name:'',
    number:0,
    id:''
  },
  fetch(id){
    return axios.get(`/books/${id}`).then((response)=>{
      this.data = response.data
      return response
    })
  },
  updata(data){
    let id = this.data.id
    return axios.put(`/books/${id}`,data).then((response)=>{
      this.data = response.data
      return response
    })
  }
}

model首先有一个data初始值,然后fetch函数发一个get请求,然后取到响应的data再把它赋值给model的data,updata函数也是一样的。

let view = {
  el:'#app',
  template:`
    
书名:《__name__》 数量:__number__
`, render(data){ let html = this.template.replace('__name__',data.name) .replace("__number__",data.number) $(this.el).html(html) } }

view里面有操作的元素el:'#app',然后是HTML模板,render函数接受一个data然后用data里面的name和number来替代模板HTML里的对应元素,再把新的HTML渲染到el里面

let controller = {
  init(options){              //init接受一个对象{view:view,model:model}
    let view = options.view
    let model = options.model
    this.view = view                      //把view和model绑到controller上面
    this.model = model
    this.view.render(this.model.data)    //页面做一个初始化,把model里面data的初始值渲染到页面
    this.bindEvents()                  //绑定事件
    this.model.fetch(1).then(()=>{
      this.view.render(this.model.data)   
    })                  //拿到拦截机返回的response然后赋值到model的data上,render函数渲染拿到的data到页面
  },
  addOne(){   
    var oldNumber=$("#number").text()
    var newNumber = oldNumber-0+1
    this.model.updata({number:newNumber})   //这里的this是addOne,后面bind(this)之后才是controller
      .then(()=>{
      this.view.render(this.model.data)
    })
  },
  minus(){   
    var oldNumber=$("#number").text()
    var newNumber = oldNumber-0-1
    this.model.updata({number:newNumber})
      .then(()=>{
      this.view.render(this.model.data)
    })
  },
  reset(){
    var newNumber = 0
    this.model.updata({number:0})
      .then(()=>{
      this.view.render(this.model.data)
    })
  },
  bindEvents(){
    $(this.view.el).on("click",'#add',this.addOne.bind(this))  //第一个this是controller,bind(this)让addOne里面的this和外面的一样都是controller
    $(this.view.el).on("click","#minus",this.minus.bind(this))
    $(this.view.el).on("click","#reset",this.reset.bind(this))
  }
}

这样mvc三部分就写完了!
那么为了避免每一个页面都要重新写一遍这三个模型,于是想到可以写一个构造函数,然后每次就只用new就可以了
思路是把私有的属性放到构造函数里,调用的时候传进去,把公用属性放到原型里

function Model(options){
  this.data = options.data
  this.resource = options.resource
}
Model.prototype.fetch = function(id){
  return axios.get(`/${this.resource}s/${id}`).then((response) => {
      this.data = response.data
      console.log(this.data)
      return response
    })
}
Model.prototype.update = function(data){
  let id = this.data.id 
    return axios.put(`/${this.resource}s/${id}`, data).then((response) => {
      this.data = response.data 
      console.log('response')
      console.log(response)
      return response
    })
}
let model = new Model({
  data: {
    name: '',
    number: 0,
    id: ''
  },
  resource: 'book'
})
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)
}
let view = new View({
  el: '#app',
  template: `
    
书名:《__name__》 数量:__number__
` })

接下来引入Vue,Vue强制把data传给view,因为Vue需要用data来初始化
template,不需要render。Vue会把当前model的data里的所有属性更新到View上面,所以直接修改View的值view.book = model.data这样直接替换了之前的render函数,只需要更新view里的data,就会自动更新HTML。

let view =new Vue({
  el:'#app',
  data:{
    book:{   
      name:'未命名',
      number:0,
      id:"" 
    },
    n:1
  },
  template:`
    
书名:《{{book.name}}》 数量:{{book.number}}
N 的值是 {{n}}
//绑定事件
`, created(){ model.fetch(1).then(()=>{ this.book = model.data }) }, methods:{ addOne(){ model.updata({ number:this.book.number+(this.n-0) }) .then(()=>{ view.book = model.data }) }, minus(){ model.updata({ number:this.book.number-(this.n-0) }) .then(()=>{ view.book = model.data }) }, reset(){ model.updata({ number:0 }) .then(()=>{ view.book = model.data }) } } })

可以使用v-model指令在元素上进行双向数据绑定。
双向数据绑定:之前我们可以通过book.number=3来修改内存值,然后Vue根据修改的内存值去更新里的数字,只就是单向绑定。如果我们引入标签,当我们修改标签里的数字,这时Vue会根据修改的数据来修改内存值,这就是双向绑定。

你可能感兴趣的:(说说axios和mvc)