vue學(xué)習(xí)記錄第四天

鉤子函數(shù)的生命周期

根實(shí)例,在初始化時會調(diào)用很多方法,這些方法被稱為鉤子函數(shù)
生命周期:beforeCreate created beforeMount mounted beforeUpdate updated beforeDestory destoryed

beforeCreate(){},此時只有內(nèi)部方法

此方法一般用不到

create(){}

獲取ajax,初始化操作

beforeMount(){}編譯前的操作,也沒有什么實(shí)際意義

一定要保證有編譯的元素el,否則會中斷
掛載el,也可以使用

new Vue().mount('#app')

如果有實(shí)例template屬性,會用模板替換掉外部html,只要有此屬性,app中的內(nèi)容沒有任何意義,template中只能有一個根元素。

let vm=new Vue(){
el:"#app",
template:"</div>{{a}}</div>",
data:{a:1
}}

之前第三天的時候又提到過,DOM中也有一個tempelate標(biāo)簽,是沒有任何意義,用來包裹元素的。

mounted(){} 操作DOM

用編譯好的el替換掉el,然后調(diào)用mounted()
真實(shí)dom渲染完了可以操作dom了

beforeUpdate(){}

當(dāng)數(shù)據(jù)變化的時候,調(diào)用beforeUpdate()

updated(){}

一般用watch來替換,watch能夠更準(zhǔn)確的知道是誰更新了。

beforedestory(){}銷毀前,可以清除定時器,或清除事件綁定

destoried(){}銷毀后

watch,computed以及方法全部被銷毀

實(shí)例上的方法

this.$data vm上的數(shù)據(jù)
this.$watch 監(jiān)控
this.$el 當(dāng)前el元素
this.$set 后加的屬性實(shí)現(xiàn)響應(yīng)式的變化
this.$options 獲取vm中所有的屬性
this.$nextTick(){} 異步方法,可以等待dom完成后獲取vm,是當(dāng)前代碼全部執(zhí)行完畢后,執(zhí)行
另外dom渲染是異步的,想要數(shù)據(jù)變化后想獲取真實(shí)dom中的內(nèi)容,必須使用nextTick
this.$refs 所有refs的集合,假如有一個標(biāo)簽 ref="myp" 可以直接通過this.$ refs.myp。ref 被用來給DOM元素或子組件注冊引用信息。如果dom元素不是通過v-for循環(huán)出來的,只能獲取一個,通過v-for則可以獲取多個,輸出為數(shù)組

組件

可以將很復(fù)雜的頁面分割成若干個獨(dú)立組件,每個組件包含自己的邏輯和樣式
減少邏輯復(fù)雜度,實(shí)現(xiàn)了代碼的重用

頁面級組件:1、一個頁面是一個組件
2、將可復(fù)用的部分抽離出來,作為基礎(chǔ)組件

優(yōu)點(diǎn)

  1. 提高開發(fā)效率
  2. 方便重復(fù)使用
  3. 便于協(xié)同開發(fā)
  4. 更容易被管理和維護(hù)

Vue的組件

一個自定義的標(biāo)簽Vue就會把它看成一個組件
div p span a header section都是W3C規(guī)定的,不是自定義的標(biāo)簽,但是Vue可以給它們賦予一定的意義

全局組件

聲明一次,可以在任何地方使用
一般使用局部組件,寫插件的時候使用全局組件
之前Vue.filter("函數(shù)名",函數(shù))全局過濾器

全局組件的基本形式

一個對象可以看成是一個組件

    Vue.component('polarbear',{
      //一個對象可以看成一個組件
      template:'<div>{{msg}}</div>',
      //只能是一個根元素
      //相當(dāng)于用這個模板替換這個標(biāo)簽
      //組件名不要帶有大寫,多個單詞用-
      //只要組件名和定義名字相同是可以的(首字母可以大寫)
      //html采用的短橫線隔開命名法 js中轉(zhuǎn)駝峰也是可以的
      data(){
        //組件中的數(shù)據(jù)必須是函數(shù)類型的,返回一個實(shí)例作為數(shù)組的實(shí)例
        return {msg:'大白白熊'}
      }
    })

組件名

組件名不要帶有大寫,有多個單詞用-
只要組件名和定義名字相同是可以大寫的,但是只有首字母可以大寫
html采用的短橫線隔開命名法,js的轉(zhuǎn)駝峰法也可以

template屬性

DOM中的template是一個沒有意義的標(biāo)簽,用來框東西
這里的template會給出一個DOM模板,替換標(biāo)簽中的內(nèi)容
只能是一個根元素

template:'<div>{{msg}}</div>'

data

組件中的函數(shù)必須是函數(shù)類型的,并且返回一個實(shí)例作為數(shù)組的實(shí)例

DOM

<div id="app">
<polarbear>大白熊</polarbear>
</div>

雖然DOM中是大白熊,但是polarbear的template屬性給出了內(nèi)容為大白白熊,所以頁面中的內(nèi)容會被替換

局部組件

必須告訴這個組件是屬于誰的

三步驟

  1. 創(chuàng)建這個組件
  2. 注冊這個組件
  3. 引用這個組件

創(chuàng)建組件

和創(chuàng)建Vue的過程相似,但是要記住組件的data是函數(shù),需要返回一個形式與Vue data形式相同的對象

    let polarbear={
      template:'<div>大白白熊</div>',
      data(){
        return {msg:'大白白熊'}
      }
    };
    let penguin={
      template:'<div>企鵝</div>'
    };
  1. 如果組件共用了數(shù)據(jù),數(shù)據(jù)會同時刷新,而組件的特點(diǎn)就是獨(dú)立性,所以最好不要
  2. 子組件不能直接使用父組件的數(shù)據(jù)
  3. 組件理論上可以無限嵌套

注冊組件

在Vue實(shí)例中添加一個components屬性

    let vm=new Vue(
    {
      el:"#app",
      data:{
        a:1
      },
      components:{
        polarbear,
        penguin
        //它們的parent是vm
        //不能跨作用域調(diào)用vm的data,組件相互獨(dú)立不能直接跨作用域 vm的實(shí)例也是一個組件
        //也擁有生命周期函數(shù)
      },
    }
    )
  1. 在哪里注冊組件,這些組件的父組件就是誰
  2. 但是組件是不能調(diào)用父組件的數(shù)據(jù)的,polarbear和penguin都不能調(diào)用a
  3. 這些組件也有生命周期函數(shù)

DOM的寫法

除了直接在DOM中寫,也可以在Vue實(shí)例中添加

template:'<polarbear><penguin></penguin></polarbear>'

注意以上這種寫法是不會顯示企鵝的,因?yàn)閜olarbear會替換掉標(biāo)簽之中的所有內(nèi)容包括penguin

組件之間引用

如果要在一個組件中使用另一個組件

  1. 首先必須要保證使用的組件真實(shí)存在
  2. 在需要引用這個組件的實(shí)力上通過components注冊這個組件
  3. 組件需要在父級的模板中通過標(biāo)簽的
    形式引入
    let littlebear={
      template:"<div>小白熊</div>"

    };
    let polarbear={
      template:'<div>白熊<littlebear></littlebear></div>',
      components:{littlebear}
    };
    let bigbear={
      template:'<div>大白熊<polarbear></polarbear></div>',
      components:{polarbear}
    };
    let vm=new Vue( 
    {
      el:"#app",
      components:{bigbear},
      template:"<bigbear></bigbear>"
}

最終顯示結(jié)果是大白熊 白熊 小白熊
除了標(biāo)簽的簡單引用,想要數(shù)據(jù)之間的引用就需要使用其他的方法了

父傳子

父親定義好數(shù)據(jù),通過屬性的方式傳遞給孩子
以父親給孩子零花錢為例

  1. 首先父親中要有money這個數(shù)據(jù)
  2. 孩子通過DOM獲取

DOM中數(shù)據(jù)傳遞

    <div id="app">
      父親給了{(lán){money}}
      <child :m="money/2"></child>
      <!--m是屬于child的屬性,1是屬于父級的,當(dāng)前組件的屬性=父級的值-->
      <!--用冒號把值變成屬性,不加冒號,money就變成字符串了,key:value,這里永遠(yuǎn)是字符串-->
    </div>

這里有標(biāo)簽的相關(guān)知識,在一個標(biāo)簽中

  1. key:value形式,前面的key是當(dāng)前組件的屬性,后面value是父級標(biāo)簽的值
  2. 如果不使用冒號的方式,傳遞的值會變?yōu)樽址袷剑褂妹疤枺禃優(yōu)閷傩缘男问?br> 如果上文中
    :m="money"改為m="money"
    那么m是字符串money

props屬性

props中的數(shù)據(jù)可以是數(shù)組,也可以是對象
但是不能和data中的名字相同,校驗(yàn)時不能阻斷代碼的執(zhí)行,只是進(jìn)行警告

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

prop使得父子prop之間形成了單向下行綁定,父級prop的更新會向下流動到子組件中。

prop:['m']

會在當(dāng)前子組件上聲明一個m屬性,值是父親的
m不能直接寫m必須寫成字符串格式

m可以直接用,但是不能改,只能通過data或者compute計(jì)算新的值

computed:{
money(){
return this.m
}}

這時

child:{
          template:'<div>兒子 {{money}}</div>',
          //props:['m'],
          computed:{
            money(){
              return this.m
            }
          }
        

顯示結(jié)果為兒子獲得50

props校驗(yàn)功能

可以使用對象的形式進(jìn)行校驗(yàn)

type

校驗(yàn)屬性的類型

type可以師原生構(gòu)造函數(shù)中的一個
String,Number,Boolean,Array,Object,Date,Function,Symbol

如果傳遞的屬性類型不正確,只會warn并不會報(bào)錯

default

默認(rèn)值,如果沒有傳數(shù)據(jù)過來,自動取默認(rèn)值

required

當(dāng)這個屬性為true時,此屬性必須傳遞,不傳就報(bào)warn,不能和default同時使用
不傳遞的時候顯示會是false

validator(val){}

自定義校驗(yàn)器
第一個參數(shù)是當(dāng)前傳遞的值
返回true則表示通過,false為不通過
但是false也只是warn,不報(bào)錯

      props:{
        //屬性名和data中的名字不能相同,校驗(yàn)時不能阻斷代碼的執(zhí)行,只是進(jìn)行警告
        m:{
          //校驗(yàn)屬性的類型,如果不帶冒號,得到的是字符串
          type:[String,Boolean,Function,Object,Arrey,Number],
          //對象的形式可以進(jìn)行校驗(yàn)
          //默認(rèn)值,如果不傳的話,自動取默認(rèn)值
          default:0,
          //required:true
          //此屬性必須傳遞,不傳就報(bào)warn,現(xiàn)在{{money}}顯示為false,但是不能和default同時使用
          validator(val){
            //第一個參數(shù)是當(dāng)前傳遞的值
            //返回true表示通過
            //false表示不通過
            //依然只是warn,自定義校驗(yàn)器,用的不是很多
            return val>300
          }
        }
      }

全部程序

  <body>
    <div id="app">
      {{money}}
      <child :m="money/2"></child>
    </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let vm=new Vue( //parent組件
    {
      el:"#app",
      data:{
        money:100
      },
      components:{
        child:{
          template:'<div>兒子 {{money}}</div>',
          computed:{
            money(){
              return this.m
            }
          },
      props:{
        m:{
          type:[String,Boolean,Function,Object,Arrey,Number],
          default:0,
          //required:true
          validator(val){
           return val>300
          }
        }
      }
      }
    }
    )
    </script>
  </body>

發(fā)布訂閱模型

發(fā)布emit 訂閱 on
說白了就是觸發(fā)和綁定
利用這兩個事件,可以創(chuàng)建一對多的關(guān)系
實(shí)例,創(chuàng)建一個{日常行為:['睡覺','游泳','吃海豹']}

function polarbear(){
  this._events={}
  //下劃線表示是私有的
  //{日常行為:['睡覺','游泳','吃海豹']}
}
let pb=new polarbear()

on

為polarbear綁定on,emit事件
因?yàn)槭撬袑?shí)例共用的,所以放在原型上

polarbear.prototype.on=function(eventName,callback){
  if(this._events[eventName]){
    //不是第一次
    //不能用點(diǎn),點(diǎn)是返回字符
 this._events[eventName].push(callback)
  }
  else{
    this._events[eventName]=[callback]
  }
}

為日常行為綁定相關(guān)事件

let sleep=(who)=>{console.log(who+"睡覺")}
let swim=(who)=>{console.log(who+"游泳")}
let eat=(who)=>{console.log(who+"吃海豹")}
pb.on('日常行為',sleep);
pb.on('日常行為',swim);
pb.on('日常行為',eat);

emit

原型綁定

polarbear.prototype.emit=function(eventName,...args){
  if(this._events[eventName])
  {
this._events[eventName].forEach(cb=>cb(...args)))
    //cb.apply(this,args)
    //展開數(shù)組
    //只運(yùn)行數(shù)組第一項(xiàng)
  }
}

這個過程是將emit后面的值賦給前面的事件
因?yàn)閰?shù)的數(shù)量不確定,使用ES6中的...args,將剩余的參數(shù)作為數(shù)組args存儲

pb.emit('日常行為','我','熊大','熊二');

最終運(yùn)行結(jié)果 我睡覺 我游泳 我吃海豹,如果想要每一個都運(yùn)行,還是要取args.length去做

子傳父

通過事件,子觸發(fā)父的事件,傳遞數(shù)據(jù)
兒子不能改變父親的值,但是可以告訴他讓他改
父親綁定一些事件,兒子觸發(fā)這個事件,將參數(shù)傳遞過去,單向數(shù)據(jù)流,父親數(shù)據(jù)刷新,兒子也隨之刷新
子傳父超復(fù)雜,饒了180個彎

  1. 首先既然觸發(fā)父的事件,那父親里必須有這個事件
  2. 然后得把這個事件綁定到子組件上
  3. 綁定后還要觸發(fā)這個事件,讓父親的方法執(zhí)行
  4. 那觸發(fā)這個事件還要在子組件上定義一個事件

事件綁定兒子上

    <div id="app">
      父親給{{money}}
      兒子得<child :m="money" @childmessage="changemoney"></child>
      </div>

changemoney是父親的事件,childmessage屬于兒子
相當(dāng)于child.on('childmessage',changemoney)

父親事件定義

    methods:{
      changemoney(val){
        this.money=val
      }
    }

兒子上的事件

template:'<div><button @click="getmoney()">多要錢</button></div>'

觸發(fā)兒子自定義事件,父親的方法被執(zhí)行

              getmoney(){
                //觸發(fā)自己的自定義事件,讓父親的方法執(zhí)行
                this.$emit('childmessage',800)
              }

將800的值傳遞給childmessage,通過觸發(fā)childmessage事件,執(zhí)行父組件的changemoney,最終money被改變?yōu)?00
全部程序

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      父親給{{money}}
      兒子得<child :m="money" @childmessage="changemoney"></child>
      <!--child.on('childmessage',changemoney),把事件綁定在兒子上-->
      </div>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!--父親綁定一些事件,兒子觸發(fā)這個事件,將參數(shù)傳遞過去,單向數(shù)據(jù)流,父親數(shù)據(jù)刷新,兒子就刷新-->
    <!--兒子不能改父親的值,但是可以告訴他,讓他改-->
    <script>
      let vm=new Vue(
      {
        el:"#app",
        data:{money:400},
        components:{
          child:{
            template:'<div><button @click="getmoney()">多要錢</button></div>',
            props:['m'],
            methods:{
              getmoney(){
                //觸發(fā)自己的自定義事件,讓父親的方法執(zhí)行
                this.$emit('childmessage',800)
              }
            }
          }
        },
        methods:{
          changemoney(val){
            this.money=val
          }
        }
      }
      )
      </script>
  </body>
</html>

.sync的用法 語法糖

.sync修飾符
是一種雙向綁定
但是雙向綁定會帶來一定維護(hù)的問題
sync修飾符相當(dāng)于將emit處的方法名改變?yōu)閡pdate:m

  <child :m.sync="money"></child>
<!--相當(dāng)于<child :m="money" @update:m="val=>{this.money=val}"></child>-->

然后再子組件

              getmoney(){

                this.$emit('update:m',800)
              }

模態(tài)框?qū)嵗?/h1>

這個實(shí)例是點(diǎn)擊主界面上的按鈕彈出警告框,然后點(diǎn)擊警告框上的關(guān)閉按鈕,關(guān)閉這個警告窗
需要利用bootstrap的警告框,子組件向父組件傳遞事件,父組件向子組件傳遞數(shù)據(jù)

  1. 父組件中定義flag屬性,true的時候顯示警告窗,false時不顯示
  2. 將flag傳遞到子組件
  3. 子組件關(guān)閉按鍵按下時觸發(fā)自定義事件執(zhí)行父組件的改變flag的方法
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet"  integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
    <div id="app">
      <button @click="clickparent">彈</button>
        <modal :show="flag" @close="fn"></modal>
        <!--:show="flag"這是父傳子,@close="fn"是子傳父-->
      <!--如果show的值為true則顯示,如果是false則隱藏 @close對應(yīng)的函數(shù)是點(diǎn)擊關(guān)閉按鈕時觸發(fā)的函數(shù)-->
      <!--<dialog :show="" @close="fn"></dialog>-->
    </div>
    <template id="dialog">
      <div class="container" v-show="show">
        <div class="row">
          <div class="col-md-6 col-md-offset-3">
              <div class="alert alert-danger" style="height:200px" role="alert">
                <button class="pull-right" @click="closealert">關(guān)閉</button>
              </div>
          </div>
        </div>
      </div>
    </template>
  </body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let modal={
        template:'#dialog',
        props:['show'],//接收父組件的屬性
        methods:{
        closealert(){
          this.$emit('close')
        }
        }
      }
      let vm=new Vue({
        el:"#app",
        components:{
        modal//名字不能叫dialog,原生已經(jīng)占用了這個名字
      },
      data:{
        flag:false
      },
      methods:
      {
        clickparent(){
          this.flag=true
        },
        fn(){
          this.flag=false
        }
      }
      })
    </script>
</html>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • # 傳智播客vue 學(xué)習(xí)## 1. 什么是 Vue.js* Vue 開發(fā)手機(jī) APP 需要借助于 Weex* Vu...
    再見天才閱讀 3,613評論 0 6
  • vue概述 在官方文檔中,有一句話對Vue的定位說的很明確:Vue.js 的核心是一個允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,270評論 0 25
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨(dú)立版本,Vue即被注冊為全局變量,可以在頁面使用了。 如果希望搭建...
    Awey閱讀 11,096評論 4 129
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,079評論 0 29
  • 我想我已經(jīng)工作了499.5天 我想,我應(yīng)該已經(jīng)工作了499.5天了吧 剛剛好 就在上周,參加了公司最后一批的現(xiàn)場招...
    胖啄木鳥閱讀 271評論 0 0