1. 程式人生 > 實用技巧 >23.Vue中雙向資料繫結是如何實現的

23.Vue中雙向資料繫結是如何實現的

vue中如何實現資料的雙向繫結

  vue中如何實現資料的雙向繫結
  vue中的指令
      v-cloak:
      v-model(表單元素設定了之後會忽略掉value,checked,selected)
      v-text:代替 {{}} 渲染成文字(不會識別html標籤)可以防止網速卡慢時{{}}出現在頁面上
      v-html:把html字元渲染成html

      v-once:只繫結一次(不能寫成v-once=”msg”)
      v-bind:動態地繫結一個或多個特性
      v-for:遍歷陣列、物件、字串、數字
      條件渲染:v-if v-else-if v-else與v-show
      v-show
      v-on:監聽 DOM 事件(v-on:click可縮寫為@click)

      自定義指令
  vue中的修飾符
    表單修飾符
    事件修飾符
  表單元素雙向資料繫結(雙向同步)
    單選框
    複選框
    下拉框
  Vue中的Class樣式與style樣式動態繫結(動態的優先順序高於原來的)
  根據hash實現單頁面開發

vue中如何實現資料的雙向繫結

實現檢視變化資料跟著變:分兩步,上面get中的為第二步(即再次讀取的時候會呼叫get方法得到之前設定的值,以此來實現動態改變) 由於直接寫obj.name = this.value;會導致迴圈呼叫set方法,所以要藉助中間物件的形式把值賦給中間物件,獲取obj.name的時候我們獲取中間物件的最新值即可
let  obj = {name:'zhufeng',age:9};//資料
let temp = {name:"lily"};//藉助中間物件
let input1 = document.getElementById("box2");//檢視
//對某一個物件使用了Object.defineProperty方法之後就要寫對應的get和set方法了,不然無法像操作普通物件一樣訪問或者設定它的屬性
//此方法不相容IE8及以下
Object.defineProperty(obj,"name",{
    configurable:true,//屬性是否可刪除
    writable:false,//屬性是否可修改
    enumerable:false,//屬性是否可列舉
    get(){//獲取obj的屬性名對應的屬性值時會呼叫該方法
       /*2*/ return temp['name'];
    },
    set(val){//設定obj的屬性名對應的屬性值時會呼叫此方法

        //實現檢視變化資料跟著變:分兩步,上面get中的為第二步(即再次讀取的時候會呼叫get方法得到之前設定的值,以此來實現動態改變)
        //由於直接寫obj.name = this.value;會導致迴圈呼叫set方法,所以要藉助中間物件的形式把值賦給中間物件,獲取obj.name的時候我們獲取中間物件的最新值即可
        /*1、*/ temp.name=val;

        //實現資料變化檢視改變
        input1.value=val;
    }
});
//為了初始化的時候讓檢視中(文字框中)有值:出現obj.name說明要訪問這個屬性就會用到defineProperty中的get方法
input1.value=obj.name;
//實現檢視改變資料跟著改變
input1.addEventListener("input",function(){
    obj.name = this.value;//當值變化時會呼叫set方法
},false);

vue中的指令

dom元素的行間屬性,vue提供了內建的指令,必須以v-開頭,後面的值均為變數

v-cloak:

消除頁面剛載入時會看到{{}}閃一下的效果,可加給最外層的根元素;

 //需要新增對應的css樣式
    [v-cloak]{
      display: none;
    }

v-model(表單元素設定了之後會忽略掉value,checked,selected)

讓表單元素和資料實現雙向繫結(對映關係)

 <input type="text" v-model="msg">

v-text:代替 {{}} 渲染成文字(不會識別html標籤)可以防止網速卡慢時{{}}出現在頁面上

{{}} 中的值都會解析成文字內容;

{{msg}}等價於<div v-text="msg"><!--此處不能再寫內容,防止出現閃的效果--></div>

v-html:把html字元渲染成html

 <div v-html="msg"></div>

v-once:只繫結一次(不能寫成v-once=”msg”)

    <div v-once>{{msg}}</div>

v-bind:動態地繫結一個或多個特性

// 繫結一個屬性
<img v-bind:src="imageSrc">
//可縮寫為如下形式,此時:src後面的值就可以是變數、表示式、賦值運算、計算、三元運算子(儘量少寫邏輯運算)
<img :src="imageSrc">//此時imageSrc就代表一個變數

v-for:遍歷陣列、物件、字串、數字

解決了迴圈問題,更高效,會在原有的基礎上進行修改,會複用原有的結構,不會修改所有DOM

要迴圈建立哪一個標籤就在那一個標籤上加v-for,後面的迴圈最好用in,用of有時會報錯迴圈陣列或物件使用v-for指令
  <div v-for="(val,index) in msg">
          {{val,index}}//msg為陣列時,val為陣列中的每一項,index為索引
  </div>  
  <div v-for="(value,key,index) in msg">
      {{key}}={{value}}{{index}};//msg為物件時,key為物件中的每個屬性名,value為屬性值,index為索引
  </div>  

條件渲染:v-if v-else-if v-else與v-show

v-if v-else-if v-else:條件滿足才渲染v-if所在標籤以及標籤內的內容;(操作的是DOM結構)

  • 設定條件判斷的DOM元素必須是連續的
  • 操作的是DOM元素
  • key 管理複用的元素 若不想複用DOM元素,只需要給相應的DOM元素增加不同的key值
  • 支援 template 標籤
  • 頻繁的顯示和隱藏用v-if會很浪費效能(操作的是DOM結構),此時要用v-show(操作的是CSS樣式)
<div id="app"> <button @click="flag=!flag">請點選</button> //template標籤是vue提供給我們的沒有任何實際意義,用來包裹元素用的(v-show不支援template標籤) <template v-if="flag"> <label>登入</label> <input type="text" key="1">//key 管理複用的元素 若不想複用DOM元素,只需要給相應的DOM元素增加不同的key值 </template> <template v-else> <label>註冊</label> <inputtype="text"key="2"> </template> </div> let vm=new Vue({ el:'#app', data:{ flag:true } });

v-show

條件滿足才讓v-show所在標籤以及標籤內的內容顯示(操作的是元素的css樣式),不支援 template 標籤

 <input type="text" v-show="flag">//flag為true時,input框才顯示

v-on:監聽 DOM 事件(v-on:click可縮寫為@click)

可以用 v-on 指令監聽 DOM 事件,並在觸發時執行一些 JavaScript 程式碼(在methods物件中定義的方法,而且methods中的方法名不能和data中的變數名一樣)

 <div v-on:click ="fn1('zhaosi,$event')">{{msg}}</div>
    <div @click ="fn1('zhaosi,$event')">{{msg}}</div>//上面的簡寫 
    方法後面可加()可不加。不加的話預設會傳入事件物件e,
    加()代表要傳引數,如果要用事件物件,則需要傳$event

自定義指令

可通過在vue例項的directives:{}屬性中賦予自定義指令意義

<div id="app">
     <button v-color="flag">變色</button>
  </div>
  let vm=new Vue({
     el:'#app',
     data:{
         flag:true
     },
     directives:{//在這裡賦予對應自定義指令意義
         //可直接寫對應的指令不用寫v-
         color(el,val){
         //el和val都是預設給的:el指的是指令所繫結的DOM元素,val是一個物件,裡面儲存的是有關指令的資訊,可用val.value獲取到指令繫結的變數(或者表示式)所代表的值,這裡就是flag所代表的值 'red'
         el.style.background=val.value;
         }
     }
  });

vue中的修飾符

表單修飾符

  • v-model.number:將使用者的輸入值轉為數值型別
  • v-model.lazy:在表單觸發change事件時更新資料,而非觸發input事件時更新資料
  • v-model.trim:自動過濾使用者輸入的首尾空白字元

事件修飾符

  • @click.stop:阻止點選事件的傳播(往上傳播和往下傳播都會被阻止)
  • @submit.prevent:阻止點選提交按鈕時的預設行為(阻止事件的預設行為)
  • @click.capture:點選的時候讓事件在捕獲階段執行;
  • @click.once:只在第一次點選的時候讓繫結的事件執行;
  • @click.self:只有點選的事件源是自己的時候觸發事件;(判斷事件源)

表單元素雙向資料繫結(雙向同步)

使用v-model屬性可讓input中的內容和資料實現雙向同步,但是使用了v-model屬性之後,input的value、checked、select屬性都會失效

<div id="app">
    <input type="text" v-model="msg">
</div>
<script src="vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app',//vue的屬性和方法對哪個DOM根元素起作用(對它的後代元素也起作用)
        //資料
    如果data中屬性的值是一個數組,如果想改變陣列中內容,只能使用原生的會修改原陣列的方法進行修改,普通的 陣列[索引]=值 不行;
        data:{//寫在data中的屬性都會掛載到當前例項上
            msg:'zhufeng'
        }
    });
    console.log(vm.msg);//'zhufeng'
</script>

單選框

對於單選框和複選框來說,加了v-mdel屬性後,初始設定的value屬性不會失效;

 <div id="app">
      <input type="radio" v-model="msg" value="男">男
      <input type="radio" v-model="msg" value="女">女
      {{msg}}
   </div>
  let app3=new Vue({
     el:'#app',
     data:{
       msg:'男'//預設選中的項,值與value的值對應,點選女的時候msg就會動態改為女
     }
   });

複選框

單個複選框:

 <div id="app">
    //複選框中加了v-model後value依然可用
        <input type="checkbox" v-model="msg">
    </div>
    let app3=new Vue({
        el:'#app',
        data:{
        //如果是複選框且只有一個的時候,會把msg的值轉化為布林值,如果為true,代表選中
            msg:false//為false時代表預設不選中
        }
    });

多個複選框,需要繫結到同一個陣列,而且要給input設定初始value值,為了在後面選中的時候獲取到對應的選中框的值

 <div id="app">
      //複選框中加了v-model後value依然可用
        <input type="checkbox" v-model="msg" value="吃飯">吃飯
        <input type="checkbox" v-model="msg" value="睡覺">睡覺
        <input type="checkbox" v-model="msg" value="敲程式碼">敲程式碼
        {{msg}}
    </div>
        new Vue({
          el: '#app',
          data: {
            msg: [] //此處的msg需要是一個數組
          }
        })

下拉框

   <div id="app">
    //加了multiple後就變為多選框,用ctrl+左鍵點選多選,msg也要換為一個數組
        <select v-model="msg" multiple>
        //加了disabled時候使用者就不能選中此項了
        //option中的value是給寫程式碼的人看的
            <option value="0" disabled>請選擇地區</option>
            <option value="1">北京</option>
            <option value="2">上海</option>
            <option value="3">浙江</option>
        </select>
        {{msg}}//如果option的value屬性不寫,則取的是option中的內容
    </div>
    let app3=new Vue({
        el:'#app',
        data:{
            msg:'0'//預設選中的某一項,值與每一個option的value值對應
        }
    });

Vue中的Class樣式與style樣式動態繫結(動態的優先順序高於原來的)

:class=”{}”或者:class=”[]
通過:class=”{}”或者:class=”[]來動態的繫結class樣式,與原來的class樣式不衝突。
有兩種方式:
1、物件的方式繫結
2、陣列的方式繫結

 <div id="app">
<!--以物件的方式動態繫結class樣式:當flag為true時,z樣式生效。y樣式不生效-->
        <div class="x" :class="{z:flag,y:false}">我的世界</div>
<!--以陣列的方式動態繫結class樣式:y,z兩個樣式都會生效-->
       <div class="x" :class="[y,z]">我的世界</div>
    </div>
    let vm=new Vue({
        el:'#app',
        data:{
            flag:true
        }
    });

:style=”{}”或者:style=”[]”:繫結行內的樣式
通過上述的方式來動態繫結行內的樣式

<div id="app">
 //第一種是物件的方式
     <div :style="{backgroundColor:'red',color:'pink'}">我是誰</div>
//第二種是陣列的方式
     <div :style="[str1,str2]">我的世界</div>
 </div>
    let vm=new Vue({
        el:'#app',
        data:{
            str1:{backgroundColor:'blue'},
            str2:{color:'yellow'}
        }
    });

根據hash實現單頁面開發

通過hash記錄跳轉的路徑(可以產生歷史管理)
瀏覽器自帶的歷史管理方法history(history.pushState(),push到哪裡就跳轉到哪裡),可能會導致404錯誤(因為使用者可能會隨意輸入路徑)
開發時使用hash的方式,上線的時候使用history的方式
[使用hash儲存]

//儲存:儲存的時候要把儲存的物件轉換成字串
 localStorage.setItem('todo',JSON.stringify(obj));
//獲取:獲取的時候要把字串轉換成物件
JSON.parse(localStorage.getItem('todo'));