从 jQuery 到 VUE 手艺栈

当前前端最炽热的框架当属 VUE,在进修 VUE 之前先来看下 VUE 的内部是怎样事变的。

我们从最基本的页面操纵最先做起。

用 jQuery 操纵页面

我们来完成一个页面,当点击按钮式,页面上的数字增添或削减

<div class="app">
  <div class="book">
    书本:《JavaScript高等程序设计》
    数目:<span class='number'>2</span>
  </div>
  <button class='addOne'>加1</button>
  <button class='minusOne'>减1</button>
  <button class='reset'>清零</button>
</div>

用 jQuery 操纵它很轻易完成需求

let log = console.log.bind(console)     //把console.log 替代成 log 少办理代码
$('.addOne').on('click',()=>{
  let oldHtml = $('.number').text()
  let newHtml = oldHtml -0 +1
  $('.number').html(newHtml)
})
$('.minusOne').on('click',()=>{
  let oldHtml = $('.number').text()
  let newHtml = oldHtml -0 -1
  $('.number').html(newHtml)
})
$('.reset').on('click',()=>{
  $('.number').text('0')
})

axios 完成 ajax

我们实在的需求是,当点击按钮时,操纵的时数据库里的数据,而不是直接在页面中操纵。

这里引入一个库axios,能够完成在前端模仿背景,它有一个主要的 API:interceptors,能够完成在它上面 Mock 数据

// 我们要的数据
let book = {
  name:'JavaScript高等程序设计',
  number:2,
  id:''
}
axios.interceptors.response.use((response)=>{
  //下面这句等价于 let {url,method,data} = response.config
  let {config:{url,method,data}} = response        // 这里的 data 是要求体
  if(url === '/book/1' && method === 'get'){
     response.data = book    //这里的 data 是响应体
  }else if(url === '/book/1' && method === 'put'){
    data = JSON.parse(data)
    Object.assign(book,data)     //要求体 data,assign可完成部份更新
    response.data = book        //响应体 data
  }
  return response
})

页面中的数据我们应该用占位符替代,数据猎取到以后 更新到页面中

//刚进入页面后的数据加载
axios.get('/book/1').then(({data})=>{
  let oldHtml = $('.app').html()
  let newHtml = oldHtml.replace('__name__',data.name) 
    .replace('__number__',data.number)    //用实在数据替代占位符
  $('.app').html(newHtml)
})
$('.app').on('click','.addOne',()=>{
  let oldNumber = $('.number').text()
  let newNumber = oldNumber -0 +1
  axios.put('/book/1',{number:newNumber}).then(({data})=>{    //要求时更新最新数据
    $('.number').html(data.number)
  })
})
$('.app').on('click','.minusOne',()=>{
  let oldNumber = $('.number').text()
  let newNumber = oldNumber -0 -1
  axios.put('/book/1',{number:newNumber}).then(({data})=>{
    $('.number').html(data.number)
  })
})
$('.app').on('click','.reset',()=>{
  axios.put('/book/1',{number:0}).then(({data})=>{
    $('.number').html(data.number)
  })
})

如许的意大利面条似的写法,异常不利于后期保护,我们应该用 MVC 优化下

用 MVC 优化

猎取数据,更新数据的事变交个model去做,model内里有三个属性:datafetchupdata;离别用来:data担任存储最新数据,fetch担任页面加载时向服务器猎取数据,并将数据存储到data中,updata担任及时页面操纵时,更新页面数据,并将最新数据保存到data中。

let model ={
  data:{    //model 内部用来存储数据
    name:'',
    number:0,
    id:''
  },
  fetch(id){
    return axios.get(`/books/${id}`).then((response)=>{
      this.data = response.data        //加载更新向 axios 猎取的数据
      return response      
    })
  },
  updata(id,data){
    return axios.put(`/books/${id}`,data).then((response)=>{
      this.data = response.data        //点击按钮向 axios 猎取最新数据,要求中的 data 是最新数据
      return response
    })
  }
}

操纵页面交给viewview有三个属性,离别是eltemplaterenderel担任视图部份,也就是你须要操纵的 DOM,template是假造的html,并经由过程render去衬着。

let view = {
  el:'.app',
  template:`
    <div>
      <div class="book">
        书本:《__name__》
        数目:<span class='number'>__number__</span>
      </div>
      <button class='addOne'>加1</button>
      <button class='minusOne'>减1</button>
      <button class='reset'>清零</button>
    </div>`,
  render(data){
    let newHtml = this.template.replace('__name__',data.name)    
      .replace('__number__',data.number)    //把占位符替代成数据
    $(this.el).html(newHtml)
  }
}

事宜相干的交给controller操纵,有两个主要的属性:initbingEvents;初始化时须要传入两参数viewmodel,背面操纵的都是在的viewmodel都是在controller身上,而不是直接操纵model

let controller = {
  init({view,model}){
    this.view = view
    this.model = model
    this.bindEvents()
    this.model.fetch(1).then(()=>{  
      view.render(this.model.data)
    })
  },
  bindEvents(){
    $(this.view.el).on('click','.addOne',this.addOne.bind(this)) //这里 addOne 内部的 this 应该是点击的谁人元素,所以这里要绑一下 this
    $(this.view.el).on('click','.minusOne',this.minusOne.bind(this))
    $(this.view.el).on('click','.reset',this.reset.bind(this))
  },
  addOne(){
    console.log(1)
    let oldNumber = $('.number').text()
    console.log(2)
    let newNumber = oldNumber -0 +1
    console.log(3)
    this.model.updata(1,{number:newNumber}).then(()=>{
        $('.number').html(this.model.data.number)
    })
    console.log(4)
  },
  minusOne(){
    let oldNumber = $('.number').text()
    let newNumber = oldNumber -0 -1
    this.model.updata(1,{number:newNumber}).then(()=>{
      $('.number').html(this.model.data.number)
    })
  },
  reset(){
    this.model.updata(1,{number:0}).then(()=>{
      $('.number').html(this.model.data.number)
    })
  }    
}
controller.init({view:view,model:model})

优化 MVC

如今是一个页面,这也写没有关系,但假如有许多页面,每一个页面中的viewmodelcontroller都反复了,这里把一些公用的要领写在原型上。

在页面中运用model,只须要通报两参数

function Model({data,resouce}){
  this.data = data
  this.resouce = resouce
}

Model.prototype.updata = function(id,data){
  return axios.put(`/${this.resouce}s/${id}`,data).then((response)=>{
    this.data = response.data
    return response
  })
}

Model.prototype.fetch = function(id){
    return axios.get(`/${this.resouce}s/${id}`).then((response)=>{
      this.data = response.data
      return response      
    })
}
let model = new Model({
  data:{
    name:'',
    number:0,
    id:''
  },
  resouce:'book'  
})

view也是,页面运用时,传两个参数就 ok 了

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:`
    <div>
      <div class="book">
        书本:《__name__》
        数目:<span class='number'>__number__</span>
      </div>
      <button class='addOne'>加1</button>
      <button class='minusOne'>减1</button>
      <button class='reset'>清零</button>
    </div>`
})

Controller公用的要领比较少,这里就没有优化了

VUE

理解了 MVC 以后再来看 VUE 就会很简朴,VUE 简朴来讲就是 MVC 中的 V,但它和 MVC 有点区分,就是它须要model中的数据

let view = new Vue({
  el:'.app',
  data:{
    book:{
       name:'我是书本',
       number:0,
       id:'' 
     },
    n:1
  },
  template:`
    <div>
      <div class="book">
        书本:《{{book.name}}》
        数目:<span class='number'>{{book.number}}</span>
      </div>
      <button class='addOne'>加1</button>
      <button class='minusOne'>减1</button>
      <button class='reset'>清零</button>
    </div>`
  }

VUE 会把data里的属性提升为 Vue 的属性,所以下面操纵能够直接用Vue.name操纵,而不是写Vue.data.name,所以我们能够在这些属性表面套一层book,用Vue.book就能够对这些属性举行批量操纵。

Vue没有render要领,那你会说它怎样完成衬着页面呢?

它供应了一个叫created的要领,在内里直接修正Vuedata属性,它就会自动帮你衬着页面

  created(){
    model.fetch(1).then(()=>{
      this.book = model.data
    })

固然 VUE 的野心不止于此 ,它以至帮你省下controllor,你都不须要举行事宜绑定

<button class='addOne' v-on:click="addOne">加1</button>
<button class='minusOne' v-on:click="minusOne">减1</button>
<button class='reset' v-on:click="reset">清零</button>

它在templatev-on:click的一个要领,它会帮你挪用methods中的要领,你只须要将点击实行的函数写在上面即可。

methods:{
    addOne(){
      model.updata(1,{number:this.book.number + (this.n-0)})
        .then(()=>{
          this.book = model.data
        })
    },
    minusOne(){
      model.updata(1,{number:this.book.number - (this.n-0)})
        .then(()=>{
          this.book = model.data
        })
    },
    reset(){
      model.updata(1,{number:0})
        .then(()=>{
          this.book = model.data
        })
    }
}    

学会了 MVC 以后在来看 VUE,就变的很简朴

MVVM

VUE 还完成另一个双向绑定的功用,我如今点击按钮只能+1-1,假如我要完成操纵+n或减n呢?

这里用input完成,在按钮上面增加一行

<div>
    <input v-model='n'>N的值是<span>{{n}}</span>
</div>

固然Vuedata中也要增加一个n

当你在input中输入响应值时,背面N的值会响应变化,这就是 MVVM。

    原文作者:UCCs
    原文地址: https://segmentfault.com/a/1190000016143559
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞