Let's VUE[1]

webdq發表於2018-04-28

簡介

Vue (讀音 /vjuː/,類似於 view) 是一套用於構建使用者介面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注檢視層,不僅易於上手,還便於與第三方庫或既有專案整合。另一方面,當與現代化的工具鏈以及各種支援類庫結合使用時,Vue 也完全能夠為複雜的單頁應用提供驅動。

指令

v-bind 動態的繫結資料

<div v-bind:color="color"></div>
// 簡寫形式
<div :color="color"></div>
複製程式碼

v-text 更新元素的文字內容

<div v-text="content"></div>
複製程式碼

v-html 更新元素的 innerHTML

<div v-html="content"></div>
複製程式碼

v-cloak 隱藏未編譯的 Mustache 標籤直到例項準備完畢 配合樣式使用

//樣式
[v-cloak]{
  display: none;
}

<div id="app" v-cloak>
  {{content}}
</div>
複製程式碼

v-once 只渲染一次

<div v-once>只渲染一次: {{content}}</div>
複製程式碼

v-for 迴圈

//迴圈陣列
<div id="app">
  <ul>
    <li v-for="book in books">{{book}}</li>
  </ul>
  <ul>
    <li v-for="(book,index) in books">{{index}} - {{book}}</li>
  </ul>
</div>

new Vue({
  el: '#app',
  data: {
    books: ['javascript','nodejs','vuejs']
  }
})
複製程式碼

迴圈陣列結果

//迴圈物件
<div id="app">
  <ul>
    <li v-for="value in user">{{value}}</li>
  </ul>
  <ul>
    <li v-for="(value,key) in user">{{key}} : {{value}}</li>
  </ul>
  <ul>
    <li v-for="(value,key,index) in user">{{index}} - {{key}} : {{value}}</li>
  </ul>
</div>

new Vue({
  el: '#app',
  data: {
    user: {
      name: 'js',
      age: 18,
      city: 'china'
    }
  }
})
複製程式碼

迴圈物件結果

v-if 根據表示式的值的真假條件渲染元素和移出元素

<div v-if="true">我被渲染了</div>
<div v-if="false">我不會被渲染</div>
複製程式碼

v-show 根據表示式的值的真假條件,切換元素的display屬性

<div v-show="true">我顯示了</div>
<div v-show="false">我隱藏了</div>
複製程式碼

v-model 在表單控制元件或者元件上建立雙向繫結

<div>
  <input v-model="message" type="text" />
</div>
<h2>{{message}}</h2>

new Vue({
  el: '#app',
  data: {
    message: 'hello vue'
  }
})
複製程式碼

v-on 繫結事件處理函式監聽 DOM 事件,簡寫為@

<div v-on:click="clickHandle">點選事件</div>
<div @click="clickHandle">點選事件</div>

// 需要手動傳入$event事件物件
<div v-on:click="clickHandle($event,params)">點選事件</div>

//事件處理函式中的this都指向例項

new Vue({
  el: '#app',
  data: {},
  methods: {
    clickHandle(event,params){
      console.log(event)
    }
  }
})
複製程式碼

事件修飾符

  • .stop 阻止冒泡
  • .prevent 阻止預設事件
  • .capture 捕獲事件
  • .self 事件源是本身才出發
  • .once 只觸發一次
  • .left 點選滑鼠左鍵時觸發
  • .right 點選滑鼠右鍵時觸發
  • .middle 點選滑鼠中鍵時觸發

按鍵修飾符

  • .enter
  • .tab
  • .delete
  • .es
  • .space
  • .up
  • .down
  • .left
  • .right
new Vue({
  el: '#app',
  data: {},
  methods: {
    clickA(){
      alert('我是A');
    },
    clickB(){
      alert('我是B');
    }
  }
})
複製程式碼
//阻止冒泡
<div @click="clickA">
  我是A
  <div @click.stop="clickB">
    我是B
  </div>
</div>
複製程式碼
//self
<div @click="clickA">
  我是A
  <div @click.self="clickB">
    我是B
  </div>
</div>
複製程式碼
//捕獲
<div @click="clickA">
  我是A
  <div @click.capture="clickB">
    我是B
  </div>
</div>
複製程式碼
//阻止預設事件
<a @click.prevent href="http://www.juejin.com">阻止預設事件</a>
複製程式碼
//只觸發一次
<div @click.once="clickA">只觸發一次</div>
複製程式碼

選項卡例項

<style>
button.active{
  background: yellow;
}
.card{
  padding: 10px;
  width: 500px;
  height: 500px;
  border: 1px solid #ccc;
  display: none;
}
.card.active{
  display: block;
}
</style>
複製程式碼
<div id="app">
  <div>
    <button v-for="(book,index) in books" @click="showTab(index)" :class="{active: tabIndex==index}"  type="button">{{book.name}}</button>
  </div>

  <div v-for="(book,index) in books" :class="{active: tabIndex==index}" class="card">
    <h2>{{book.name}}</h2>
    <p>{{book.info}}</p>
  </div>
</div>
複製程式碼
new Vue({
  el: '#app',
  data: {
    books: [
      {
        name: 'javascript',
        info: 'JavaScript一種直譯式指令碼語言,是一種動態型別、弱型別、基於原型的語言,內建支援型別。'
      },
      {
        name: 'nodejs',
        info: 'Node.js是一個Javascript執行環境(runtime environment),釋出於2009年5月,由Ryan Dahl開發,實質是對Chrome V8引擎進行了封裝。'
      },
      {
        name: 'vuejs',
        info: 'Vue是一套用於構建使用者介面的漸進式框架。'
      }
    ],
    tabIndex: 0
  },
  methods: {
    showTab(i){
      this.tabIndex = i;
    }
  }
})
複製程式碼

雙向資料繫結

雙向資料繫結

Vue將資料物件和DOM進行繫結,彼此之間互相產生影響,資料的改變會引起DOM的改變,DOM的改變也會引起資料的變化

雙向資料繫結

MVVM模式

MVVM模式

<div>
  <input v-model="message" type="text" />
</div>
<h2>{{message}}</h2>

new Vue({
  el: '#app',
  data: {
    message: 'hello vue'
  }
})
複製程式碼

響應式原理

  • 把一個普通的 JavaScript 物件傳給 Vue 例項的 data 選項
  • Vue 將遍歷此物件所有的屬性,並使用 Object.defineProperty 把這些屬性全部轉為 getter/setter
  • Vue內部會對資料進行劫持操作,進而追蹤依賴,在屬性被訪問和修改時通知變化

Object.defineProperty

  • 作用:直接在一個物件上定義一個新屬性,或者修改一個物件的現有屬性
  • 語法:Object.defineProperty(obj, prop, descriptor)
  • 引數:(物件,屬性,屬性描述符/存取器描述)
[屬性描述符]

  是否可配置刪除,預設false
  configurable: false

  是否可列舉,預設false
  enumerable: false

  屬性值,預設undefined
  value: undefined

  是否可被重寫,預設false
  writable: false

[存取器描述]

  獲得屬性值的方法
  getter: function(){}

  設定屬性值的方法
	setter: function(){}
複製程式碼
//新增修改物件屬性
let obj = {
  a: 1,
  b: 2
}
Object.defineProperty(obj, 'a', {
  value: 3
});
Object.defineProperty(obj, 'c', {
  configurable: true,
  enumerable: true,
  value: 4,
  writable: true
});
console.log(obj) //{a: 3, b: 2, c: 4}
複製程式碼
  • 使用defineReactive劫持資料
//劫持資料
function observer(data,cb){
  Object.keys(data).forEach( (key) => {
    defineReactive(data,key,data[key],cb)
  })
}
//轉換getter,setter
function defineReactive(obj,key,value,cb){
  Object.defineProperty(obj,key,{
    get(){
      return value;
    },
    set(newValue){
      value = newValue;
      cb(newValue);
    }
  })	
}
複製程式碼
  • 使用Proxy劫持資料
function observer(data,cb){
  return new Proxy(data,{
    get(target,attr){
      return target[attr];
    },
    set(target,attr,newValue){
      target[attr] = newValue;
      cb(newValue);
    }
  });
}
複製程式碼
<button id="btn" type="button">改變內容</button>
<div id="content"></div>

let content = document.querySelector('#content');
let btn = document.querySelector('#btn');
let data = {
  text: 'Vue是一套用於構建使用者介面的漸進式框架。'
}
observer(data,function(newVal){
  content.innerHTML = newVal;
})
content.innerHTML = data.text;
btn.onclick = function(){
  data.text = '內容改變了';
}
複製程式碼

選項

data

Vue 例項的資料物件

methods

事件處理器

computed

  • 計算屬性定義在computed中,它不是方法,屬性的值是函式的返回值。
  • 把對處理資料的邏輯抽離在計算屬性中,使得模板更加輕量易讀
  • 計算屬性的值會被快取,並根據依賴的資料變化而重新計算
//預設設定的get函式
new Vue({
  el: '#app',
  data: {
    a: 1
  },
  computed: {
    b(){
      return 2;
    }
  }
})
//設定get,set函式
new Vue({
  el: '#app',
  data: {
    a: 1
  },
  computed: {
    b: {
      get(){
        return 2;
      },
      set(newVal){
        this.b = newVal;
      }
    }
  }
})
複製程式碼

watch

watch觀察 Vue 例項上的資料變動,鍵是需要觀察的表示式,值是對應回撥函式

let vm = new Vue({
  el: '#app',
  data: {
    html: 'html',
    js: {
      javascript: 'javascript',
      nodejs: 'nodejs',
      vuejs: 'vuejs'
    }
  },
  watch: {
    html(newVal,oldVal){
      console.log(newVal,oldVal) // -> 改變html html
    }
  }
})
vm.html = '改變html';
複製程式碼
//深度監控
let vm = new Vue({
  el: '#app',
  data: {
    html: 'html',
    js: {
      javascript: 'javascript',
      nodejs: 'nodejs',
      vuejs: 'vuejs'
    }
  },
  watch: {
    'js.vuejs':{
      handler(newVal,oldVal){
        console.log(newVal,oldVal) // -> 改變vuejs vuejs
      },
      deep: true
    }
  }
})
vm.js.vuejs = '改變vuejs';
複製程式碼
//偵聽開始之後被立即呼叫
let vm = new Vue({
  el: '#app',
  data: {
    html: 'html',
    js: {
      javascript: 'javascript',
      nodejs: 'nodejs',
      vuejs: 'vuejs'
    }
  },
  watch: {
    html:{
      handler(newVal,oldVal){
        console.log(newVal,oldVal) // -> html undefined
      },
      immediate: true
    }
  }
})
複製程式碼

響應的資料變化

  • Vue.set( target, key, value )
  • vm.$set( target, key, value )
<div id="app">
  <button @click="addCity1" type="button">Vue新增城市屬性</button>
  <button @click="addCity2" type="button">vm新增城市屬性</button>
  <ul>
    <li v-for="(value,key) in user">{{key}} : {{value}}</li>
  </ul>
</div>

new Vue({
  el: '#app',
  data: {
    user: {
      name: 'js',
      age: 18
    }
  },
  methods: {
    addCity1(){
      Vue.set( this.user, 'city', 'china' )
    },
    addCity2(){
      this.$set( this.user, 'city', 'china' )
    }
  }
})
複製程式碼

相關文章