1. 程式人生 > 實用技巧 >前端 ---- vue的認識

前端 ---- vue的認識

const 只能放常量!!!!!!!!!!!!!!!!

基礎使用:
	<body>
		<div id='vue'>
			<div v-clock>{{msg}}</div>
			<div v-text='msg'></div>
			<div v-html='html'></div>
		</div>
		
		<script src='./js/jquery.js'></script>
		<script src='./js/vue.js'></script>
		<script type='text/javascript'>
			var vm = new Vue({
				el:'#vue',
				data:{
					msg:'hello world2',
					html:'<h2>重大喜訊</h2>'
				}
			})
		</script>
	</body>
	1. 例項引數分析
		el: 元素的掛載位置(值可以是CSS選擇器或者DOM元素)
		data:模型資料(值是一個物件)
	2. 插值表示式用法
		將資料填充到HTML標籤中
		插值表示式支援基本的計算操作
	3. Vue程式碼執行原理分析
		概述編譯過程的概念(Vue語法→原生語法)

1.v-cloak  防止閃動
 當插值沒被解析時,會顯示{{msg}}而不是解析內容
 背後的原理:先通過樣式隱藏內容,然後在記憶體中進行值的替換,替換好之後再顯示最終的結果
2.v-text
    - v-text指令用於將資料填充到標籤中,作用於插值表示式類似,但是沒有閃動問題
    - 如果資料中有HTML標籤會將html標籤一併輸出
    - 注意:此處為單向繫結,資料物件上的值改變,插值會發生變化;但是當插值發生變化並不會影響資料物件的值
3.v-html
    - 用法和v-text 相似  但是他可以將HTML片段填充到標籤中
    - 可能有安全問題, 一般只在可信任內容上使用 `v-html`,**永不**用在使用者提交的內容上
    - 它與v-text區別在於v-text輸出的是純文字,瀏覽器不會對其再進行html解析,但v-html會將其當html標籤解析後輸出。
4.v-pre
 v-pre  輸入什麼顯示什麼,即使是{{msg}}也不會被解析
5.v-once
    v-once 只編譯一次,後面如果有資料響應式來修改內容也不會編譯,暴力原有樣式
    v-once的應用場景:如果顯示的資訊後續不需要再修改,你們可以使用v-once,這樣可以提高效能。否則就會一直監聽是否有資料響應式
6.v-model
    雙向資料繫結
    - 當資料發生變化的時候,檢視也就發生變化
    - 當檢視發生變化的時候,資料也會跟著同步變化
    
    一些使用心得:
        1.有點像name,但他的值對應的是value,如下面這個程式碼,
        如果要選擇按鈕的選中狀況可以直接傳入陣列 hobby:['1','2'],然後通過this.hobby來獲取整個陣列,this.hobby.toString()能獲得具體內容
          <div>
            <span>愛好:</span>
            <input type="checkbox" id="ball" value="1" v-model='hobby'>
            <label for="ball">籃球</label>
            <input type="checkbox" id="sing" value="2" v-model='hobby'>
            <label for="sing">唱歌</label>
            <input type="checkbox" id="code" value="3" v-model='hobby'>
            <label for="code">寫程式碼</label>
          </div>
          
        2.Vue中,應該這樣:<textarea v-model='desc'></textarea>  而不是<>xxxx<>
        3.<select v-model='occupation' multiple> 那occupation就應該是[]
        4.<input type="text" v-model.trim='info'> 只會去掉文字前面和後面的空格,中間的空格不會被去掉

7.v-on:click   --->@click
    1.事件呼叫中  @click='say'中自帶event事件,,預設第一個是引數物件,所以函式中接受的引數第一個是event
    2.而@click='say($event)'需要傳入event事件,名字固定且必須放到最後,所以函式中接受的引數最後一個是event
    如果傳入<div v-text='num'></div>中的num,那麼就可以進行操作,但不會改變num的值
8.事件繫結
    1.事件修飾符 可以自定義
        1.v-on:click.stop  .stop阻止冒泡   冒泡:下級標籤的觸發會傳遞到上級的標籤去
            傳統阻止冒泡的方法
            handle1:function (event) {
                            event.stopPropagation();
                        },
        2.v-on:click.prevent  .prevent阻止預設行為   如a標籤的預設跳轉
            傳統的行為是在標籤中加入點選事件的函式,然後在函式中呼叫 event.preventDefault()
            <a href="http://www.baidu.com" @click='fn'>百度</a>
            fn:function (event) {
                                event.preventDefault();
                            },
        3.可以串聯一起寫,如v-on:click.stop.prevent  但是寫的時候是有順序的
        4.因為提供的事件是有限的,所以可以通過自定義的方法來新增想要的事件
        Vue.config.keyCodes.自定義名稱= 標識、鍵值  如果不知道鍵值可以通過event.keyCode來得到鍵值
        Vue.config.keyCodes.f1= 112

        
    2.按鍵修飾符 
        1.   .enter回車鍵  <input v-on:keyup.enter='submit'>
        2.   .esc 退出鍵  <input v-on:keyup.delete='handle'>
        3.    或者直接v-on:keyup.直接跟鍵值(自定義)
9. v-bind
    <input type="text" v-bind:value="msg" v-on:input='msg=$event.target.value'>
    等價於<input type="text" v-model='msg'>

	1.繫結class
        1.繫結物件:   
            繫結的時候可以同時繫結兩個物件模板,如objClass1和objClass2,但是如果有相同的屬性會被後面的覆蓋
            <div v-bind:class='[objClass1,objClass2]'></div>   
            
        2.繫結陣列:<div v-bind:class="[activeClass, errorClass]"></div>
        3.繫結物件和繫結陣列 的區別
            - 繫結物件的時候 物件的屬性 即要渲染的類名 物件的屬性值對應的是 data 中的資料 
            - 繫結陣列的時候數組裡面存的是data 中的資料 
            
            
        4.樣式繫結相關語法細節:
          1、物件繫結和陣列繫結可以結合使用
          2、class繫結的值可以簡化操作
          3、預設的class如何處理?預設的class會保留
  2.繫結style
    1.繫結物件 <div v-bind:style="{ color: activeColor, fontSize: fontSize }"></div>
    2.繫結陣列<div v-bind:style="[baseStyles, overridingStyles]"></div>

    一些細節與class一樣
   
10.v-if和v-show
    1.v-if 
        使用場景
            1- 多個元素 通過條件判斷展示或者隱藏某個元素。或者多個元素
            2- 進行兩個檢視之間的切換
            <div id="app">
                    <!--  判斷是否載入,如果為真,就載入,否則不載入-->
                    <span v-if="flag">
                       如果flag為true則顯示,false不顯示!
                    </span>
            </div>

            <script>
                var vm = new Vue({
                    el:"#app",
                    data:{
                        flag:true
                    }
                })
            </script>
    2.v-show   如果是false 就會有display:none  這個屬性,如果是true,就沒有這個屬性   
    3.v-show 和 v-if的區別
        v-show本質就是標籤display設定為none,控制隱藏
          - v-show只編譯一次,後面其實就是控制css,而v-if不停的銷燬和建立,故v-show效能更好一點。
        v-if是動態的向DOM樹內新增或者刪除DOM元素
          - v-if切換有一個區域性編譯/解除安裝的過程,切換過程中合適地銷燬和重建內部的事件監聽和子元件
11.v-for
    用於迴圈的數組裡面的值可以是物件,也可以是普通元素  
    基本使用:
        <ul id="example-1">
           <!-- 迴圈結構-遍歷陣列  
            item 是我們自己定義的一個名字  代表數組裡面的每一項  
            items對應的是 data中的陣列-->
          <li v-for="item in items">
            {{ item.message }}
          </li> 

        </ul>
        <script>
         new Vue({
          el: '#example-1',
          data: {
            items: [
              { message: 'Foo' },
              { message: 'Bar' }
            ],
           
          }
        })
        </script>
   
    :小提示
        - 不推薦同時使用 `v-if` 和 `v-for`
        - 當 `v-if` 與 `v-for` 一起使用時,`v-for` 具有比 `v-if` 更高的優先順序。
   

   v-for 中的Key的作用  1.相當於一個唯一標識,2.key的作用主要是為了高效的更新虛擬DOM
    如果有ABC那麼Key分別為0,1,2,index也0,1,2,但是,如果把A刪了,那麼Key就對應1,2,而index對應的是0,1
    所以在資料中,如果Key沒變,就不需要重新去渲染這個資源,可以在一定程度上提高效能(簡單來說就是遍歷是時候加上:key就好了)

        1 .index值不是一定不變的,如果不加key值的話,刪除前面的項。後面的index可能變也可能不變,比如加個定時器的時候會變,不加定時器不會變
        2 .不加key的話,更新機制的進行diff的時候是會全部比較的,比如刪除第一個的話,後面的元素其實都不一樣,會一項一項的比較。然後全部元素都替換,沒有做到最小更新。而且裡面的傳的值也會變,如果這個時候你要根據裡面的值刪除元素的話,就會出錯,尤其是加了定時器之後
        3 .所以這個key值對資料改變之後的diff更新比較有很大的效能提升,或者說有了key和沒有key是兩種比較和更新機制
        4 .使用v-for更新已渲染的元素列表時,預設採用舊地複用策略,會複用之前的元素,有的時候使用index來做為key值,其實不是特別推薦的。可能會發生變化,最好是時間戳加上一個自增的數字

        5 .如果有key的話,就會根據key值去判斷某個是否修改,重新渲染這一項

    ------PS:
        在原生JS中,for遍歷建議使用在物件中,不建議對陣列使用

        6 .虛擬dom的diff演算法


    v-for遍歷陣列
    v-for遍歷物件


12..lazy
    .lazy,把input變成change,  input是隻要輸入就會觸發事件,而change是改變才會觸發事件
    在下面程式碼中的文字框中,Input事件是隻要你輸入內容,div中的內容就會一直變化,而如果是change事件,則會在輸入框失去焦點後使div的內容改變
    <input type="text" v-model.lazy='msg'>
    <div>{{msg}}</div>
13.自定義指令
		第一個focus是名稱,第二個focus是dom指令,el是繫結的元素相當於this,而bind是傳入的引數
		Vue.directive('focus',{
			inserted:function (el,bind) {
				// body...
				el.focus();
			}
		})
		使用:<input type="text" v-focus>
	鉤子函式:大部分只用到bind和inserted
		1.bind:只調用一次,指令第一次繫結到元素時呼叫。在這裡可以進行一次性的初始化設定。
		2.inserted:被繫結元素插入父節點時呼叫 (僅保證父節點存在,但不一定已被插入文件中)。
		3.update:所在元件的 VNode 更新時呼叫,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新 (詳細的鉤子函式引數見下)。
		4.componentUpdated:指令所在元件的 VNode 及其子 VNode 全部更新後呼叫。
		5.unbind:只調用一次,指令與元素解綁時呼叫。
	鉤子函式的引數
		指令鉤子函式會被傳入以下引數:

		1.el:指令所繫結的元素,可以用來直接操作 DOM。
		2.binding:一個物件,包含以下 property:
			·name:指令名,不包括 v- 字首。
			·value:指令的繫結值,例如:v-my-directive="1 + 1" 中,繫結值為 2。
			·oldValue:指令繫結的前一個值,僅在 update 和 componentUpdated 鉤子中可用。無論值是否改變都可用。
			·expression:字串形式的指令表示式。例如 v-my-directive="1 + 1" 中,表示式為 "1 + 1"。
			·arg:傳給指令的引數,可選。例如 v-my-directive:foo 中,引數為 "foo"。
			·modifiers:一個包含修飾符的物件。例如:v-my-directive.foo.bar 中,修飾符物件為 { foo: true, bar: true }。
		3.vnode:Vue 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。
		4.oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。
	
14.區域性指令(只能在本元件使用(這個Vue中))
	如果想註冊區域性指令,元件中也接受一個 directives 的選項: 
	-------------------------元件是啥?---------------------- Vue例項物件就是一個元件(暫時)

	new Vue(
	data,
	directives: {{
	  focus: {
		// 指令的定義
		inserted: function (el) {
		  el.focus()
		}
	  }
	}

	})

	使用方法跟全域性自定義函式一樣 v-color='msg'

15.計算屬性  計算屬性是這樣使用的{{msg}}msg是計算屬性的名稱,但可能也是data中的資料
	跟方法或自定義指令看起來差不多,使用的話{{reverseDmessage}}  直接函式名,不用加括號msg是因為 msg:xxx
	computed:{ 
		reverseDmessage:function(){
			console.log(11)
			return this.msg.split('').reverse().join('')
		}

16.計算屬性和方法的區別
	之前說差不多這兩個差不多,那麼有什麼區別呢?
	1.計算屬性是基於他們的依賴進行快取的(有快取)
	2.方法不存在快取

	計算屬性:如果使用上面的計算屬性,然後呼叫兩次{{reverseDmessage}},只會執行一次console.log(11),第二次如果msg沒變,就會使用上一次的快取結果
	自定義指令:會執行兩次
17.監聽函式
    非同步和開銷比較大的操作
    watch

    在實驗中,可以通過定時器來模仿後臺介面呼叫(都是非同步的),
    在定時器中this是window下的this,所以要在外面設定變數來獲得this
          methods:{
            check:function (name) {
              var that = this
              // body...
              setTimeout(function () {
                // body...
                if(name == '小明'){
                  that.tip ='名字已經有了'
                }else{
                  that.tip = '名字可以用'
                }
              },1000)
            }
          }


18.過濾器
    跟自定義指令有類似的地方
        Vue.filter('uper',function (val) {
          // body... charAt取第0位,toUpperCase變成大寫,slice從第1位開始取
          return val.charAt(0).toUpperCase()+val.slice(1)
        })
    使用:
        <div>{{msg | upper }}</div>  msg就是val,upper是過濾器名稱,
        <div>{{msg | upper | XXX | XXXX}}</div> 會把前面的結果傳到後面XXX
        <div v-bind:name='name | upper'></div>  或者在繫結屬性的時候

    區域性過濾器  
        filters:{
            upper:funtion(){}
        }
        
    過濾器傳引數
        <div>{{msg | upper(params) }}</div>
        Vue.filter('uper',function (val,params) {
          // body... charAt取第0位,toUpperCase變成大寫,slice從第1位開始取
          console.log(params)
          return val.charAt(0).toUpperCase()+val.slice(1)
        })


19.生命週期
    mounted  當這個函式被呼叫時,就代表初始化結束了,模板被渲染
    使用this.$destroy();就會刪除vue例項,但是渲染的模板還在

20.陣列更新方法
    1.變異方法(Vue是響應式的,就會把陣列的一些方法變成響應式的)原陣列變了
    2.替換陣列  返回一個新陣列,原陣列不變

    陣列的響應式變化
    Vue.set(vm.items,indexOfltem,newValue)
    vm.$set(vm.items,indexOfltem,newValue)
        1.要處理的陣列名稱 2.要處理的陣列索引 3.要處理的陣列的新的值
    如:vm.list[1] = 'XX' ,雖然list[1]的值會發生改變,但是已經渲染的頁面的內容不會改變,因為這樣不是響應式的
        應該要Vue.set(vm.list,1,'XX')這樣才會變   vm.$set(vm.list,1,'XX')
    物件也可以這樣賦值,中間那個也是索引Vue.set(vm.list,'XX','XX')

21.需找條件
    1.我第一時間想到for循壞來取得陣列,好像比較麻煩
        for(item in this.books){
            if(this.books[item].id == id){
              iname=this.books[item].name
            }
        }
        this.name=iname
        this.id=id

    2.用filter就是通過條件來找相應物件的,不過不管找出來幾個都是陣列,所以如果只有一個的話,取的時候要[0]
        var book=this.books.filter(function (item) {
          // body...下面這個是條件,然後把陣列返回出去
          return item.id==id
        })
        this.name=book[0].name
        this.id=book[0].id
23.刪除(this)
    1.使用some在想要刪除的時候操作
            如果在普通函式中使用this,這個this是window下的this,如下面這個函式
        
            some函式是判斷有沒有滿足條件的資料,返回true和false,但是可以在判斷後進行操作再返回結果
            this.books.some( (item)=> {
                        // body...
                         if(item.id==this.id){
                          item.name = this.name
                          return true
                         }
                    })
            應該修改成箭頭函式,箭頭函式下的this是父級作用域的this,所以跟this.books同級,
            this.books.some( (item) =>{
                          // body...
                          this.id
                        })
            如果找到想要的結果並進行操作後需要return true 不能讓迴圈繼續下去
        
   







    2.使用filter找到不想要刪的陣列,從新賦值
        this.books = this.books.filter(function(item){
            return item.id != id;
    3.用index找到單獨那個,然後刪除
        根據id從陣列中查詢元素的索引
        var index = this.books.findIndex(function(item){
        return item.id == id;
        });
        根據索引刪除陣列元素
        this.books.splice(index, 1);