Vue基礎(chǔ)知識

構(gòu)造器

  • 實例化vue時,需傳入一個選項對象,它可以包括 數(shù)據(jù)、模板、掛載元素、方法和生命周期鉤子

    屬性與方法

  • 每個vue實例都會代理其data對象里所有的屬性

  • vue實例暴露了一些有用的實例屬性與方法,這些屬性與方法都有前綴$,以便與代理的data屬性區(qū)分

    實例生命周期

  • created鉤子------在實例被創(chuàng)建后被調(diào)用

  • mounted----當編譯好的HTML被掛載到對應(yīng)的位置,這個操作完成后觸發(fā)

  • updated----當data中的數(shù)據(jù)改變,并且虛擬DOM重新渲染完成后觸發(fā)

  • destroyed

  • 概要: 鉤子的this 指向調(diào)用它的實例

    生命周期圖示

  • https://cn.vuejs.org/images/lifecycle.png

    插值

  • 文本

    • 雙大括號
    • v-text
  • 純HTML

    • v-html
  • 屬性

    • v-bind(大雙括號不能在屬性中使用,因此需使用v-bind)
  • 使用JavaScript表達式

    指令

  • 哪些指令?

    • v-bind

    • v-on

    • v-if

    • v-for(特殊)

      v-if

      <div id="app">
      <template v-if="ok==='username'">
      用戶名: <input type="text" placeholder="請輸入用戶名" key="name-input">
      </template>
      <template v-else>
      密碼: <input type="text"  placeholder="請輸入密碼" key="psd-input">
      </template>
      <button @click="toggle">點擊切換類型</button>
      </div>
      
      new Vue({
        el: "#app",
        data: {
          ok:'username'
        },
        methods: {
        toggle: function(todo){
            if(this.ok==='username'){
            this.ok = 'psd'
          }else{
            this.ok = 'username';
          }
        }
        }
      })
      
      

      v-for

      <div id="app">
      <ul>
        <li v-for="item in items">{{item}}</li>
      </ul>
      </div>
      
      new Vue({
      el: "#app",
      data: {
      items:['a','b','c']
      },
      methods: {
        toggle: function(todo){
            todo.done = !todo.done
        }
      }
      })
      
      
  • 修飾符

    • v-on
      • .stop 阻止單擊事件冒泡 <a v-on:click.stop="doThis"></a>

      • .prevent 提交事件不再重載頁面

      • .capture 添加事件偵聽器時使用時間捕獲模式

      • .self 只當事件在該元素本身(而不是子元素)觸發(fā)時觸發(fā)回調(diào)

      • 太多了,不再總結(jié).這些都不重要,大家有空自己搜一下吧~~~~哈哈

        過濾器

  • 過濾器的目的是用于文本轉(zhuǎn)換,轉(zhuǎn)化成你想要的格式,還是給大家來個例子

filters


   <div id="app">
        <p>{{message | changeChar}}</p>
       <button @click="changeFirstChar">改變</button>
    </div>

   new Vue({
    el: "#app",
    data: {
      message:'nihao'
    },
    methods: {
        changeFirstChar: function(todo){
            this.message = 'good evening'
        }
      },
      filters:{
        changeChar(value){
                if(!value){
            return '';
          }else{
            return value.charAt(0).toUpperCase()+value.substring(1)
          }
        }
      }
    })

縮寫

  • v-bind縮寫

    • 原有: <a v-bind:href="url"></a> 縮寫: <a :href="url"></a>
  • v-on縮寫

    • 原有:<button v-on:click="doSomeThing"></button> 縮寫:<button @click="doSomeThing"></button>

      計算屬性

      計算屬性(減少模板{{}}的復(fù)雜度)

  • 基礎(chǔ)例子1

  • 計算屬性的兩種寫法

computed


<div id="app">
   {{fullName}}
</div>

new Vue({
  el: "#app",
  data: {
          firstName:'Ji',
            lastName:'RenGu'
  },
     computed:{
      fullName(){
        return this.firstName+'----'+this.lastName;
    }
  }
})

  • 計算緩存vs方法(Methods)
    • 計算屬性computed具有緩存,而methods無緩存
  • Computed屬性vs 偵聽器(Watch屬性)
    • watch方法--觀察Vue實例上的數(shù)據(jù)變動,只要指定的數(shù)據(jù)改變就會執(zhí)行預(yù)定的函數(shù)

watch


    <div id="app">
        {{msg}} <br> 
        改變了嗎? {{isChange}}
        <button @click="change">改變</button>
    </div>

    new Vue({
      el: "#app",
      data: {
            msg:'欲窮千里目',
          isChange:'No'
      },
        watch:{
        //只要msg改變,這個方法就會執(zhí)行
        msg(val,oldVal){
            this.isChange = 'Yes'
        }
      },
      methods:{//不得不說ES6寫起來真爽
        change(){
            this.msg = '更上一層樓'
        }
      }
    })

* computed方法

  • 計算setter 和getter

    • get和set,顧名思義,一個是獲得,一個是設(shè)置,常規(guī)上來講,計算屬性中都是有g(shù)et和set方法的,默認是只有g(shù)etter方法,如果需要的話,自然,你也可以寫一個setter方法.來個例子,諸位往下看:

    get和set

<div id="app">
此時的onpiece: {{onepiece}} <br>
此時的msg: {{msg}} <br><br>
<button @click="setName">設(shè)置name</button>
</div>

new Vue({
el: "#app",
data: {
name:'Kobe',
msg:''
},
methods:{
setName(){
this.onepiece = 'JorDan'
}
},
computed:{
onepiece:{
get(){
return this.name +'Bryant';
},
set(newVal){
//當你給onepiece設(shè)置值的時候set就就會調(diào)用
this.msg = newVal+'is the greatest basketball player';
}
}
}
})

class與style綁定

綁定HTML class

  • 對象語法
    • 基本
    • 在對象中傳入多個class屬性(其會與原有class共存)
    • 直接傳入對象
    • 與計算屬性一起使用(綁定返回對象的計算屬性)
  • 數(shù)組語法
    • 簡單例子
    • 三元表達式
    • 當有多個條件class時,可以在數(shù)組語法中使用對象語法
  • 用在組件上
    • 簡單例子

    • 綁定HTML class例子

綁定class的幾種方式

.classC{
  color:red;
}
.classD{
  font-weight:bold;
}
.classE{
  font-size:20px;
}
.classF{
  color:blue;
}
.classM{
  display:block;
}
.classN{
  display:none;
}

<div id="app">
 <h2>class屬性綁定</h2>
-------------------綁定變量-------------------------
<div :class="{classA:a,classB:b}">
  綁定變量
</div>
 -------------------綁定對象-------------------------
<div :class="styleObj">
  綁定對象
</div>
 -------------------綁定數(shù)組-------------------------
<div :class="arrClass">
  綁定數(shù)組
</div>
  -------------------綁定三元運算符-------------------------
<div :class="m==true?'classM':'classN'">
  綁定變量
</div>
  <button @click="toggle">toggle</button>
</div>

new Vue({
  el: "#app",
  data: {
   a:true,
   b:false,
   styleObj:{
    classC:true,
    classD:true
   },
   m:true,
   arrClass:['classE','classF']
  },
  methods:{
    toggle(){
        this.m=!this.m;
    }
  }
})

### 綁定內(nèi)聯(lián)樣式
* 對象語法
    * 內(nèi)聯(lián)式對象語法
    * 樣式對象式對象語法(更推薦)
* 數(shù)組語法
* 自動添加前綴
    * v-bind:style 當需要特定的前綴時如transform,vue.js會自動添加
* 多重值
    * 從vue2.3+后,可以為一個屬性添加多個值的數(shù)組,常用于含有多個前綴的情況
例子跟上邊差不了多少,懶得寫了.相信大家應(yīng)該也都會,哈哈哈哈~~~

## 條件渲染
### v-if(v-else)是真正的渲染
* template元素與v-if
* v-else(需要緊跟在v-if后邊)
* v-else-if(vue2.1.0新增)
* 用key管理可復(fù)用的元素---(如果這個例子看不懂的話.可以在群里問我!!!)
    * 例子:用戶名和郵箱登錄界面 如果有key就不會復(fù)用,大家可以把key去試一下,然后輸入看一下效果!!!

    <div id="app">
      <template v-if="ok==='username'">
          用戶名: <input type="text" placeholder="請輸入用戶名" key="name-input">
      </template>
      <template v-else>
         密碼: <input type="text"  placeholder="請輸入密碼" key="psd-input">
      </template>
      <button @click="toggle">點擊切換類型</button>
    </div>

    new Vue({
      el: "#app",
      data: {
       ok:'username'
      },
      methods: {
        toggle: function(todo){
            if(this.ok==='username'){
            this.ok = 'psd'
          }else{
            this.ok = 'username';
          }
        }
      }
    })

### v-show(其只是簡單的切換display屬性)
* v-show不支持template語法
* v-show不支持v-else
### v-if VS v-show
* v-if
    * 當條件不成立時不會渲染
    * 切換開銷較大,適合不太可能變化的場景
* v-show
    * 無論成不成立都會渲染
    * 首次渲染開銷較大,但切換開銷小,因此適合經(jīng)常變化的場景
## 列表渲染
### v-for
* 基本用法
    * 簡單例子
    * 帶有index參數(shù)
    * 使用of 替代 in
* template v-for
    * 簡單例子
* 對象迭代 v-for
    * 基礎(chǔ)用法
    * 帶其他參數(shù)用法
* 整數(shù)迭代 v-for
    * 例子
* 組件和v-for
 包含所有類型的例子

<div id="app">
<hr>
<strong style="border:2px solid #ccc;">遍歷數(shù)組:</strong>
<ul>
<li v-for="item in items" >{{item}}</li>
</ul>
<hr>
<strong style="border:2px solid #ccc;">遍歷對象數(shù)組:</strong>
<ul>
<li v-for="(item,index) in pers">{{index}}--我是{{item.name}},今年{{item.age}}歲</li>
</ul>
<hr>
<strong style="border:2px solid #ccc;">遍歷對象:</strong>
<ul>
<li v-for="(value,key) in obj">
key:{{key}} |
value:{{value}}
</li>
</ul>
</div>

new Vue({
el: "#app",
data: {
isOK:'true',
items:['香蕉','蘋果','烤肉'],
pers:[{
name:'Kobe',
age:'40'
},
{
name:'James',
age:'38'
}],
obj:{
1:'one',
2:'two'
}
}
})

key

  • 作用

    • 用v-for更新已渲染過的列表時,它默認采用的是“就地復(fù)用”的原則,也就是如果數(shù)據(jù)項順序發(fā)生了改變,vue將不是移動DOM元素來匹配數(shù)據(jù)項的順序,而是簡單復(fù)用此處的元素。如果想跟蹤每個節(jié)點的身份,從而重用或重新排列現(xiàn)有元素,可使用key。(key還可用在v-if中,詳見v-if中的郵箱名和用戶名切換的例子)
  • 好吧,可能大家看到這里是一頭霧水,不知所以,憂心忡忡,到底key有什么卵用,剛才上邊的例子不是沒有加key嗎?好吧,不扯那沒用的,通過一個例子告訴大家key到底有啥用!!!

<div id="app">
  KEY: <input type="text" v-model="id"> 
  VALUE: <input type="text" v-model="name">
  <button @click="add">添加</button>
  <ul>
<li v-for="item in list" :key="item.id"> 
//此處你可以把key去了,先勾選一條,在追加一條試一下,然后加上key,勾選一條追加一條再試一下,一目了然
  <input type="checkbox" >
  {{item.id}}---{{item.name}}
</li>
  </ul>
</div>
new Vue({
  el: "#app",
  data: {
    id:"",
    name:"",
    list:[
      {id:1, name:'李斯'},
      {id:2, name:'嬴政'},
      {id:3, name:'趙高'},
      {id:4, name:'韓非'},
      {id:5, name:'荀子'},
    ]
  },
  methods: {
      add: function(){
        this.list.unshift({id:this.id,name:this.name})
    }
  }
})

因為加上key默認采取的就是就地復(fù)用策略

數(shù)組更新檢測

  • 變異方法(會改變原有數(shù)組)

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()
  • 重塑數(shù)組

    • filter()
    • concat()
    • slice()
  • 注意事項
    利用索引直接設(shè)置一個項時,vue不能檢測變動,如: vm.items[indexOfItem] = newValue
    那如果設(shè)置某一項的該怎么設(shè)置呢?

    • Vue.set(example1.items, indexOfItem, newValue)
    • example1.items.splice(indexOfItem, 1, newValue)

       <div id="app">
       <button @click="setZF">設(shè)置第二項為張飛</button>
       <button @click="setGY">設(shè)置第三項為關(guān)羽</button>
       <ul>
       <li v-for="item in list">
       <input type="checkbox" >
       {{item.id}}---{{item.name}}
       </li>
       </ul>
       </div>

var vmm = new Vue({
el: "#app",
data: {
id:"",
name:"",
list:[
{id:1, name:'李斯'},
{id:2, name:'嬴政'},
{id:3, name:'趙高'},
{id:4, name:'韓非'},
{id:5, name:'荀子'},
]
},
methods: {
setZF: function(){
Vue.set(this.list,1,{id:2,name:'張飛'})
},
setGY:function(){
this.list.splice(2,1,{id:3,name:'關(guān)羽'})
}
}
})

* 修改數(shù)組長度時,vue不能檢測變動,如:vm.items.length = newLength
* 只能用example1.items.splice(newLength)

對與顯示過濾/排序結(jié)果的兩種方法

  • 過濾數(shù)組--計算屬性computed例子

  • 過濾數(shù)組--方法methods例子

計算屬性應(yīng)用于過濾


<div id="app">
{{specialNum}}
</div>

new Vue({
el: "#app",
data: {
nums:[1,2,3,4,5,6,7,8,9]
},
computed:{
specialNum(){
return this.nums.filter((item,index)=>{
return item%3==0;
})
}
}
})

<div id="app">
<ul>
在v-for循環(huán)中直接嵌入方法
<li v-for="item in fil(numbers)">{{item}}</li>
</ul>
</div>

new Vue({
el: "#app",
data: {
numbers:[1,2,3,4,5,6,7,8,9]
},
methods:{
fil(nums){
return nums.filter((item,index)=>{
return item%3==0;
})
}
}
})

兩個簡單的事件處理器

先來一個簡單小例子,v-on用來綁定事件


<div id="app">
<button @click="num+=1">增加1</button>
{{num}}
</div>

* * *

<div id="app">
<button @click="sayHello">點擊sayHello</button>
</div>
new Vue({
el: "#app",
methods: {
sayHello: function(){
alert('sayHello')
}
}
})
`### 內(nèi)聯(lián)處理器方法 * 訪問原生DOM事件的例子,如果click事件不傳參數(shù),就默認把原生DOM傳遞進去`
<div id="app"> //沒有傳參數(shù),就是原生的!!!
<button @click="showBtnname">顯示按鈕的名字</button> <br><br>
{{msg}}
</div>

new Vue({
el: "#app",
data: {
msg:''
},
methods: {
showBtnname: function(e){
this.msg = e.target.innerText;
}
}
})

  • 未訪問原生DOM事件的例子,如果傳了參數(shù).那么方法中接受的第一個參數(shù)就是該參數(shù),在vue中所有的事件綁定都是這樣的

----------------------------html---------------------------------
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos">
<label>
<input type="checkbox" v-on:change="toggle(todo)" v-bind:checked="todo.done">
      <del v-if="todo.done">
        {{ todo.text }}
      </del>
      <span v-else>
        {{ todo.text }}
      </span>
    </label>
  </li>
</ol>
</div>
----------------------------js---------------------------------
new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
})
----------------------------css---------------------------------
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}

#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}

li {
margin: 8px 0;
}

h2 {
font-weight: bold;
margin-bottom: 15px;
}

del {
color: rgba(0, 0, 0, 0.3);
}

事件修飾符

  • .stop
    • 阻止單擊事件冒泡
  • .prevent
    • 提交事件不再重載頁面
  • .capture
    • 使用事件捕獲模式
  • .self
    • 只有當事件在該元素本身被觸發(fā)時(不包含子元素)才觸發(fā)回調(diào)
  • .once
    • 事件只觸發(fā)一次(vue 2.1.4新增)
  • 修飾符串聯(lián)
    • 例子

按鍵修飾符

  • .enter

    • keyCode
    • .enter
  • .tab

  • .delete

    • (捕獲 “刪除” 和 “退格” 鍵)
  • .esc

  • .space

  • .up

  • .down

  • .left

  • .right

  • 組合使用,單獨是使用的話,和click都是一樣的,這里組合使用有點特殊,使用 . 進行連接簡單給個例子

<div id="app">
<button @click.ctrl="num++">num+1</button>
{{num}}
</div>

new Vue({
  el: "#app",
  data: {
      num:0
  }
})

### vue2.1.0新增 按鍵修飾符

*   .ctrl
*   .alt
*   .shift
*   .meta

    ## 表單控件綁定

    ### 基礎(chǔ)用法

*   文本

    ```
      <div id="app">
        <h2>{{msg}}</h2>
        <br>
        <input type="text" v-model="msg">
      </div>

      new Vue({
        el: "#app",
        data: {
         msg:'萬年的msg'
        }
      })

    ```

*   多行文本---注意了啊:在文本區(qū)域插值( `<textarea></textarea>` ) 并不會生效,應(yīng)用 `v-model` 來代替

    ```
      <div id="app">
      <p  style="white-space: pre">
        {{msg}}
      </p>
        <br>
        <textarea type="text" v-model="msg"></textarea>
      </div>

    ```

*   復(fù)選框

    *   單個復(fù)選框(直接綁定true,false)

        ```
        <div id="app">
        <input type="checkbox" id="checkbox" v-model="checked">
        <label for="checkbox">{{ checked }}</label>
        </div>

        new Vue({
          el: "#app",
          data: {
           checked:true
          }
        })

        ```

    *   多個復(fù)選框(將選中的所有value綁定到一個數(shù)組)

        ```
        <div id="app">
            <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
            <label for="jack">Jack</label>
            <input type="checkbox" id="john" value="John" v-model="checkedNames">
            <label for="john">John</label>
            <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
            <label for="mike">Mike</label>
            <br>
            {{checkedNames}}
        </div>

        new Vue({
          el: "#app",
          data: {
            checkedNames:[]
          }
        })

        ```

*   單選按鈕(綁定選中的單選框的value)

    ```
      <div id="app">
      <input type="radio" id="one" value="One" v-model="picked">
      <label for="one">One</label>
      <br>
      <input type="radio" id="two" value="Two" v-model="picked">
      <label for="two">Two</label>
      <br>
      <span>Picked: {{ picked }}</span>
      </div>

      new Vue({
        el: "#app",
        data: {
          picked:''
        }
      })

    ```

*   選擇列表(不管是單選還是多選,v-model都要綁定到select元素上)

    *   單選列表(綁定到被選中項的value)

        ```
          <div id="app">
              <select v-model="selected">
                <option>A</option>
                <option>B</option>
                <option>C</option>
              </select>
              <span>Selected: {{ selected }}</span>
          </div>

          new Vue({
            el: "#app",
            data: {
              selected:''
            }
          })

        ```

  • 多選列表(綁定一個數(shù)組,數(shù)組的內(nèi)容是所有的選中項的value)

    <div id="app">
    <select v-model="selected" multiple>
      <option>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    <br>
    <span>Selected: {{ selected }}</span>
    </div>
    
    new Vue({
      el: "#app",
      data: {
        selected: []
      }
    })
    
  • 動態(tài)選項

    <div id="app">
    <select v-model="selected">
      <option v-for="option in options" v-bind:value="option.value">
        {{ option.text }}
      </option>
    </select>
    <span>Selected: {{ selected }}</span>
    </div>
    
    new Vue({
      el: "#app",
      data: {
             selected: 'A',
        options: [
          { text: 'One', value: 'A' },
          { text: 'Two', value: 'B' },
          { text: 'Three', value: 'C' }
        ]
      }
    })
    

### 修飾符

*   .lazy

    *   由原有的input事件變更為change事件

        ```
          <div id="app">
            <input type="text" v-model.lazy="msg">
            {{msg}}
          </div>

          new Vue({
            el: "#app",
            data: {
              msg:'萬年的msg'
            }
          })

        ```

*   .number

    *   將輸入的類型轉(zhuǎn)換成數(shù)字類型(NaN則還是原有類型)
*   .trim
    *   去除兩端空白

算了,這點太簡單

### v-model與組件

## 組件

### 使用組件

*   注冊

    *   注意事項

        *   在初始化根實例前一定要確保注冊了組件
        *   名稱最好 小寫(可以使用短桿)

            ```

            <div id="app">
            <my-comp></my-comp>
            </div>

Vue.component('my-comp',{
    template:'<h3>我是新出爐的組件</h3>'
})
new Vue({
  el: "#app",
  data: {

  }
})
```

*   局部注冊

    ```
      <div id="app">
        <my-comp></my-comp>
      </div>

      new Vue({
        el: "#app",
        components:{
            'my-comp':{template:'<h3>我是新出爐的組件</h3>'}
        },
        data: {

        }
      })

    ```

*   DOM模板解析說明

    *   自定義組件在這些元素內(nèi)受限

        *   ul

        *   ol

        *   table

        *   select

        *   概要: 解決方案是 使用 特殊的is屬性

            ```
            <div id="app">
            <table>

            ```
             <tr>
             <my-comp></my-comp>//注意:這樣寫是絕對錯誤的,因為tr中只允許有td,這樣寫他是不認識滴
             </tr>

            ```

            </table>
            </div>
            xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 上邊是錯誤的

    ---------------------------------下邊是正確的-----------------------------------
    <div id="app">
     <table>
       <tr>
         <td is="my-comp"></td>
       </tr>
     </table>
    </div>

    new Vue({
      el: "#app",
      components:{
          'my-comp':{
                template:'<td>我是組件td</td>'
        }
      },
      data: {

      }
    })
    ```
  • 不受限的情況--使用字符串模板

    • <script type="text/x-template"> 怎么用呢?給大家來個例子吧!

      -------------------------------HTML-----------------------------------------
      <div id="app">
       <table>
         <tr>
         <template>
             <my-comp></my-comp>
         </template>
         </tr>
       </table>
      </div>
      
      <script type="text/x-template" id="myComponent">
                  <td>This is a component!</td>
      </script>
      
      -----------------------------------JS----------------------------------
      new Vue({
        el: "#app",
        components:{
            'my-comp':{
                  template:'#myComponent'
          }
        },
        data: {
      
        }
      })
      
    • JavaScript內(nèi)聯(lián)模板字符串(第二種也給大家解釋一下是什么意思,什么是字符串模板)

      <div id="app">
       <table>
         <tr>
         <template>  //這個就是字符串模板
             <my-comp></my-comp>
         </template>
         </tr>
       </table>
      </div>
      
    • .vue組件 (第三種不解釋了,用了那么多遍了,要是還不會,我就開始瘋狂嘲笑你)

  • data必須是函數(shù),在組件中使用data中定義的數(shù)據(jù),必須使用函數(shù)返回,其實這事要說為啥,還得從根上說,我自己的理解,最根本的三個字就是作用域,目的就是為了防止組件中使用的data和vue實例中的data進行相互污染,有機會的話可以給大家講一下,但是這不是三句兩句就能講清楚的,門票一人5毛怎么樣?

    <div id="app">
    <mycomp></mycomp>
    </div>
    
    new Vue({
      el: "#app",
      components:{
          'mycomp':{
                template:'<button>{{btncount}}</button>',
           data(){
              return {btncount:8}
            }
        }
      },
      data:{
          btncount:10
      }
    })
    

Prop(子組件從父組件獲得數(shù)據(jù))

  • 使用prop傳遞數(shù)據(jù)

    •   <div id="app">
            <child msg="我是來自于父組件的內(nèi)容"></child>
        </div>
      
        new Vue({
          el: "#app",
          components:{
              'child':{
                props:['msg'],
                template:'<h2>{{msg}}</h2>'
            }
          }
        })
      
      
    • 動態(tài)綁定父組件中的數(shù)據(jù)

          <div id="app">
            <input type="text" v-model="fathertext">
                {{fathertext}}
            <child :childText="fathertext"></child>
          </div>

          new Vue({
            el: "#app",
            components:{
                'child':{
                  props:['childtext'],
                  template:'<h1>{{childtext}}</h1>'
              }
            },
            data: {
                fathertext:''
            }
          })

  • props注意事項

  • 一般情況下是數(shù)組形式,如果要想規(guī)定props的數(shù)據(jù)類型(后面用中括號 [ ])。默認值等(見props驗證),則是對象了(后面用花括號 { })

  • 關(guān)于命名:要不然全小寫,要不然kebabCase(駝峰式),kebab-case(短橫線隔開式)Vue 能夠正確識別出小駝峰和下劃線命名法混用的變量,如這里的forChildMsgfor-child-msg是同一值。

  • ,如果出不來,先檢查一下命名,看個例子:

      
      <div id="app">
        <input type="text" v-model="msg">
        <child :childMsg="msg"></child>
      </div>
    
      new Vue({
        el: "#app",
        components:{
            child:{
              template:'<h1>{{childMsg}}</h1>',
                props:['childMsg']
          }
        },
        data: {
         msg:'apple'
        }
      })
    
    
  • 動態(tài)Prop(使用v-bind):在模板中,要動態(tài)地綁定父組件的數(shù)據(jù)到子組件模板的 props,和綁定 Html 標簽特性一樣,使用v-bind綁定

    • 局部注冊組件
    • 全局注冊組件
  • 字面量語法vs動態(tài)語法

  • 單向數(shù)據(jù)流

    • 解釋

      • 父組件數(shù)據(jù)更新后,子組件的所有prop都會更新為最新值,但是反過來就不會。(注意 :如果prop為數(shù)組或?qū)ο髸r,子組件改變prop,父組件的狀態(tài)也會受到影響,因為數(shù)組或?qū)ο笫且妙愋?,他們指向同一個內(nèi)存空間。)如果子組件的prop值被修改,則vue會給出警告。試一下下邊這個例子

        <div id="app">
        <parent></parent>
        </div>
        
        let childNode = {
         template: `
             <div class="child">
              <div>
               <span>子組件數(shù)據(jù)</span>
               <input v-model="forChildMsg"/>
              </div>
              <p>{{forChildMsg}}</p>
             </div>`,
         props: {
          "for-child-msg": String
         }
        };
        let parentNode = {
         template: `
             <div class="parent">
              <div>
               <span>父組件數(shù)據(jù)</span>
               <input v-model="msg"/>
              </div>
              <p>{{msg}}</p>
              <child :for-child-msg="msg"></child>
             </div>
            `,
         components: {
          child: childNode
         },
         data() {
          return {
           msg: "default string."
          };
         }
        };
        
        new Vue({
          el: "#app",
          components:{
              parent:parentNode
          }
        })
        
        
    • 特殊情況應(yīng)對方法

      • prop作為初始值傳入后,可能子組件想把它當做局部數(shù)據(jù)來用的情況

        • 方法:定義一個局部變量,并用prop的值初始化它

          props: ['initialCounter'],
          data: function () {
            return { counter: this.initialCounter }
          }
          //直接使用counter作為子組件的局部變量就可以了
          
          
      • prop作為初始值傳入,可能子組件處理成其他數(shù)據(jù)輸出的情況,比如處理成去空格并大寫

        • 方法:定義一個計算屬性,處理prop的值并返回

          props: ['size'],
          computed: {
            normalizedSize: function () {
              return this.size.trim().toLowerCase()
            }
          }
          
          
  • prop驗證

    • 例子--代碼篇

      Vue.component('example', {
        props: {
          // 基礎(chǔ)類型檢測 (`null` 意思是任何類型都可以)
          propA: Number,
          // 多種類型
          propB: [String, Number],
          // 必傳且是字符串
          propC: {
            type: String,
            required: true
          },
          // 數(shù)字,有默認值
          propD: {
            type: Number,
            default: 100
          },
          // 數(shù)組/對象的默認值應(yīng)當由一個工廠函數(shù)返回
          propE: {
            type: Object,
            default: function () {
              return { message: 'hello' }
            }
          },
          // 自定義驗證函數(shù)
          propF: {
            validator: function (value) {
              return value > 10
            }
          }
        }
      })
      
      

自定義事件(子組件將數(shù)據(jù)傳回父組件)

  • 使用v-on綁定自定義事件

    • 給組件綁定自定義事件例子(用v-on來監(jiān)聽子組件觸發(fā)的事件)

    • 給組件綁定原生事件例子--使用native修飾符

      <div id="app">
        <btncomp @click.native="alertE"></btncomp>
      </div>
      
      new Vue({
        el: "#app",
           components:{
            btncomp:{
              template:'<button>點擊我彈出</button>'
          }
        },
        methods:{
            alertE(){
              alert(777)
          }
        }
      })
      
      
  • .sync修飾符(vue 2.3)

    • 目的:使父子組件實現(xiàn)prop類似“雙向數(shù)據(jù)綁定”(默認子組件無法更改prop的值,上邊已經(jīng)說到了,但是使用sync后子組件可以改變prop 的值,并傳回父組件)

    • 使用范例

        <div id="app">
            <child :name.sync="name"></child>  //其實不加也能更改,但是會報錯
            <button type="button" @click="changePropsInFather">在父組件中將props值改變?yōu)?props'</button>
          </div>
      
            Vue.component('Child', {
              template: `<h1 @click="changePropsInChild">hello, {{name}}</h1>`,
              props: {
                name: String,
              },
              methods:{
                changePropsInChild(){
                  this.name = 'I am from child'
                }
              },
            })
            // 實例化一個Vue對象
            const app = new Vue({
              el: '#app',
              data(){
                return {
                  name: 'world'
                }
              },
              methods:{
                changePropsInFather(){
                  this.name='I am from father'
                },
              },
            })
      
      
  • 使用自定義事件的表單輸入組件

    • v-model的語法糖(可能之前我在CNODE課程中講過,但是提的不是特別的仔細,這里還是給大家再說一下)

         <div id="app">
             <input v-model="price">
         </div>
      
          new Vue({
             el: '#app',
             data: {
                  price: ''
             }
         });
      
      

      我們對v-model已經(jīng)再熟悉不過了,一般都是像上邊這樣的用法,但是v-model只是一個語法糖,它的真身是下邊這樣:

        <div id="app">
        <input type="text" :value="price" @input="price = $event.target.value">{{price}}
        </div>
      
          new Vue({
             el: '#app',
             data: {
                  price: ''
             }
         });
      
      
* 例子

    * html及實例部分和注冊組件部分

      ```
      <div id="app">
        <price-input :value="price" @input="isinputing"></price-input>
        {{price}}
      </div>

      new Vue({
        el: "#app",
        components:{
            'price-input':{
              template:"<input type='text' @input='update($event.target.value)' />",
            props:['value'],
            methods:{
                update(val){
                  this.$emit('input',val)
              }
            }
          }
        },
        data: {
          price:''
        },
        methods: {
            isinputing: function(val){//此處的value就是子組件傳遞過來的
              this.price = val;
          }
        }
      })
      ```

非父子組件通信

  • 非父子組件通信(1 父傳子是用props 2 子傳父在vue中是不允許的,因為vue只允許單向數(shù)據(jù)傳遞,這時候我們可以通過觸發(fā)事件來通知父組件改變數(shù)據(jù),從而達到改變子組件數(shù)據(jù)的目的. 3 那么非父子組件之間通信怎么搞??????)

    • 簡單的場景---采用空實例作為中央事件總線,原理就是找一個人來當作一個中轉(zhuǎn)站!

      
       <div id="app1" @click="toApp2">
          我是組件一,點擊我給二傳值
        </div>  <br>
         <div id="app2">
           {{app2msg}}
         </div>
      
      var bus = new Vue();  // 創(chuàng)建事件中心,創(chuàng)建中轉(zhuǎn)站
      new Vue({
        el: "#app1",
        data: {},
        methods: {
            toApp2: function(){
              bus.$emit('change','上山打老虎')  //使用中轉(zhuǎn)站觸發(fā)
          }
        }
      })
      
      new Vue({
        el: "#app2",
        data: {
            app2msg:''
        },
        created(){
            bus.$on('change',(val)=>{
              this.app2msg = val; //在組件二創(chuàng)建完成的時候就使用中轉(zhuǎn)站進行監(jiān)聽
          })
        }
      })
      
      
* 復(fù)雜的場景---專門的狀態(tài)管理模式vuex

使用Slot分發(fā)內(nèi)容

  • 內(nèi)容分發(fā)概念

    • 為了讓組件可以組合(如本子主題的例子),因此需要混合父組件的內(nèi)容與子組件的自己模板,這一過程就稱作內(nèi)容分發(fā)。

        <app>
          <app-header></app-header>
          <app-footer></app-footer>
        </app>
      
        之前我們的組件,如果給app指定了模板,那么里邊的app-header和foot組件的內(nèi)容就會被覆蓋,因此,為了讓他們能夠組合.需要混用,這就是內(nèi)容分發(fā)
      
      
  • 編譯作用域

    • 分發(fā)內(nèi)容是在父作用域內(nèi)編譯的
  • 單個slot(無具名slot)

    • 為什么用slot

      • 當父組件中有內(nèi)容(即自定義的標簽名之間有元素--見本子主題的例子) 子組件模板中無slot時,則父組件中的內(nèi)容會被丟棄。

          <div id="app">
            <my-comp>
              <p>我是組件中的內(nèi)容</p>  //這個p會被覆蓋
            </my-comp>
          </div>
        
          new Vue({
            el: "#app",
            components:{
                'my-comp':{
                  template:'<h1>我是一個組件</h1>'
              }
            }
          })
        
        
        * 那么單個slot怎么用呢?

            ```
            <div id="app"> 
            <children> 
            <span>12345</span> 
            <!--上面這行不會顯示--> 
            </children> 
            </div> 

            var vm = new Vue({ 
            el: '#app', 
            components: { 
            children: { //這個無返回值,不會繼續(xù)派發(fā) 
                template: "<button><slot></slot>(我是button)</button>"
            } 
            } 
            }); 
            ```

* 當父組件中有內(nèi)容時
    * 子組件中的slot會被父組件中內(nèi)容所替換。(slot標簽也會被替換掉)
* 當父組件中無內(nèi)容時
    * 子組件中slot內(nèi)容會被顯示出來

  • 具名slot

    • 用法:保子引父(保持子組件模板,引入父組件參數(shù))--嚴格按照子組件的模板順序來即:遇到具名slot對應(yīng)的元素就渲染相應(yīng)的元素,遇到不具名的slot,則會渲染除了具名slot對應(yīng)的元素以外的所有元素。

        <div id="app">
          <children>
            <span slot="first">12345</span>
            <span slot="second">56789</span>
            <!--上面這行不會顯示-->
          </children>
        </div>
      
        var vm = new Vue({ 
        el: '#app', 
        components: { 
          children: { //這個無返回值,不會繼續(xù)派發(fā) 
            template: "<button><slot name='first'></slot>我是button<slot name='second'></slot>所以使用button標簽</button>"
          } 
        } 
        }); 
        總結(jié):說白了,就是多一個name屬性.沒啥稀奇玩意
      
      
  • 作用域插槽(特殊的插槽)

    • 作用:使用可復(fù)用模板替代已渲染元素

    • 用法:同具名slot類似,都是嚴格按照子組件的模板順序渲染,只不過遇到slot元素時會將父組件中的template元素里的元素全部渲染

      • 列表組件例子

        
        <div id="app">
        <child :items="items">
        <template slot="item" scope="props">
        <!--必須存在的具有 scope屬性的 template元素(作用域插槽的模板), props臨時的變量名稱,接受子組件中傳遞的props對象-->
        <!--slot = “item”是具名 slot的用法。-->
        <li>
        {{props.tex}}
        <!--引用子組件中綁定的tex屬性值。-->
        </li>
        </template>
        </child>
        </div>
        
        
        Vue.component('child',{
                props:["items"],
                template:'<ul><slot name="item" v-for="item in items" v-bind:tex="item.text"></slot></ul>'
            });

        new Vue({
            el:'#app',
            data:{
                items:[
                    {text:'老虎'},
                    {text:'棒子'},
                    {text:'雞'}
                ]
            }
        })
        ```

動態(tài)組件

  • 使用is屬性(注意,is前使用了v-bind!??!通過is來決定那個組件被渲染顯示 )

    
       <div id="app">
          <component v-bind:is="show"></component>
          <button v-on:click="changeShow">change show</button> 
       </div>
    
            var app=new Vue({
                  el:'#app',
                  data:{
                      show:'tem1'
                  },
                  components:{
                      tem1:{
                          template:'<div>11111111111</div>'
                      },
                        tem2:{
                          template:'<div>22222</div>'
                      },
                        tem3:{
                          template:'<div>333333</div>'
                      }
                  },
                  methods:{
                      changeShow:function(){
                          if(this.show=='tem1'){
                                  this.show='tem2'
                          }else  if(this.show=='tem2'){
                                  this.show='tem3'
                          }else{
                               this.show='tem1'
                          }
                      }
                  }
              })
    
    
  • keep-active

    • 作用:可保留組件狀態(tài)或避免重新渲染(包裹動態(tài)組件時會緩存不活動的組件實例而不是銷毀它們)配合 <keep-alive>使用時,可以保留組件狀態(tài)避免重新渲染(和v-show 比較的差別是v-show 是一開始就渲染的所有組件,而keep-alive 并不是一開始就渲染好所有組件,而已保留渲染過的組件

    • 注意事項:使用環(huán)境應(yīng)該是較大頁面頻繁切換的情景下

    • 用法

                <div id="app">
                    <component v-bind:is="show"></component>
                    <button v-on:click="changeShow">change show</button>
                </div>
      
                         var app=new Vue({
                    el:'#app',
                    data:{
                        show:'tem1'
                    },
                    components:{
                        tem1:{
                            template:'<div>11111111111</div>'
                        },
                          tem2:{
                            template:'<div>22222</div>'
                        },
                          tem3:{
                            template:'<div>333333</div>'
                        }
                    },
                    methods:{
                        changeShow:function(){
                            if(this.show=='tem1'){
                                    this.show='tem2'
                            }else  if(this.show=='tem2'){
                                    this.show='tem3'
                            }else{
                                 this.show='tem1'
                            }
      
                        }
                    }
      
                })
      
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容