vue框架深度解析之vue基礎

  • Vue實例

  1. Vue實例創(chuàng)建和作用
const app = new Vue({
  // el: '#root',
  template: '<div>{{text}}</div>',
  data: {
    text: 'text'
  }
})
app.$mount('#root')

-- 1. app.$data -> 所有data的數(shù)據(jù) [obj](app.data 和 app.data是同一個對象)(vue把app.data上的屬性代理到app.data)
-- 2. app.$props -> 所有props的數(shù)據(jù) [obj]
-- 3. app.$el -> vue組件掛載到dom上的html節(jié)點
-- 4. app.$options Vue實例對象的所有options, 包括默認和我們傳進去的通過options是無法修改Vue實例的屬性的(至少data是), 應為, Vue實例上的data并不是和options.data是同一個對象
-- 5. app.$options.render = h => { return h(div, {}, 'new render function')} -> 這里的 h其實是createElement()方法參數(shù)1. 標簽名2. 存放標簽屬性的對象4.標簽內(nèi)容(如果還是標簽,就會循環(huán)使用createElement()),也可以不傳參數(shù) h 直接使用this.$createElement()方法
-- 6. app.$root -> 指的的是掛載到真實html上的根實例對象
-- 7. app.$children -> 在父組件里通過調(diào)用children可以訪問子組件的實例 -- 8. `app.slots-> vue插槽 -> 在組件章節(jié)中會有講解 -- 9.app.scopedSlots` -> vue插槽存儲傳值的對象 -> 在組件章節(jié)中會有講解 -- 10. `app.refs-> 如果ref綁定組件到dom節(jié)點獲取模板的真實dom節(jié)點, 如果綁定到組件, 獲取組件的實例 -- 11.app.isServer` -> 判斷是否ssr -- 12. 在組件內(nèi)部可以調(diào)用parent, 獲取父組件的實例. 可以改變父組件的屬性, 不推薦, 在且只在new Vue實例的parent屬性中定義一個父組件, 這樣就可以獲取這個組件的實例, 普通組件中的組件間的關(guān)系是vue渲染中指定了, 無法修改

// comp1 可以通過this.$parent獲取comp0的實例
new Vue {
  parent: comp0
}

2.Vue實例的屬性

  1. Vue實例的方法
    -- 1. app.$mount()-> 將Vue實例掛載到真實Dom上
    -- 2. app.$watch() -> 監(jiān)聽data里的數(shù)據(jù),作用同組件內(nèi)的watch, 在組件銷毀的同事, 需要注銷掉, 否則會導致內(nèi)存溢出, 在組件內(nèi)生命的watch伴隨這組件的消亡而注銷, 而調(diào)用的$watch方法需要手動注銷
// 監(jiān)聽data數(shù)據(jù)并得到注銷watch的函數(shù)
const unWatch = app.$watch('text', (newText, oldText) => {})
// 注銷watch
unWatch()

-- 3. app.$onapp.$emit -> 用來派發(fā)(emit)和監(jiān)聽(on)事件, 必須同事作用于同一vue對象否則不會冒泡 app.$once -> 只觸發(fā)一次

app.$on('test', (a, b) => {
  console.log(`test emited ${a} $需曾`)
})
app.$emit('test', 1, 2)

-- 4. app.$forceUpdate -> 強制組件重新渲染一次

new Vue({
  ...,
  data: {
    obj: {} // vue是響應式的框架, 如果沒有聲明對象里邊的屬性而直接給這個屬性賦值, 就不是響應式的, 可以在每次調(diào)用這個屬性的時候, 執(zhí)行一次app.$forceUpdate(), 但是這樣性能太低
  }
})

-- 5. app.$set() -> 用來給date里的數(shù)組和對象添加響應式的屬性, 相當于把某些值, 補到了data里

app.$set(app.obj, 'a', 123)

-- 6. app.$delete(app.obj, 'a') -> app.$set()的對應方法: 如果直接刪除set添加的屬性, 只會刪除值, 其值的reactive還在, 會導致內(nèi)存溢出 -- 7. `app.nextTick(callback())-> 這個和js的事件隊列有關(guān), vue的渲染過程是異步的,舉個例子: 在setInterval()里, 聲明一個變量i并讓i++五次, 最后打印i的值, 得到的結(jié)果不會是, 一個一個往上加, 而是5個5個的往上加, 這就是js事件隊列 -> js會把當前的隊列都執(zhí)行一遍, 然后在循環(huán)一遍, 執(zhí)行新添加的隊列,如果是需要操作dom節(jié)點的, 肯定是要在dom全渲染完之后才行, $nextTick就是再dom完全渲染完之后, 才執(zhí)行回調(diào)(如果你拿不到dom或者值跟新了頁面沒更新, 這個時候你可能會用到$nextTick) -- 8.app.$destroy()` -> 主動銷毀組件

  • vue組件的生命周期

  1. beforeCreate() -> 組件初始化就會執(zhí)行
    -- 初始化events和 lifecycle, reactive并沒有初始化, 不要做數(shù)據(jù)的修改
  2. created()
    -- created()之后會判斷是否有el屬性, 沒有就等待$mount方法被調(diào)用,
    初始化injections 和reactive
  3. beforeMount() -> 將組件的template編譯掛載到dom上 -> $el是vue綁定到的真事dom
    中間有個 render(createElement) -> 在render之前會vue會查看是否有template屬性, 有的話, 會通過render把template渲染到頁面上, 沒有的話就會顯示vue掛載的節(jié)點
  4. mounted() -> $el是組件template里的數(shù)據(jù)
  5. beforeUpdate() -> 數(shù)據(jù)更新的時候執(zhí)行
  6. updated()
  7. activated() -> keepalive激活的時候執(zhí)行
  8. deactivated() - keepalive停用的時候執(zhí)行
  9. beforeDestroy() - 組件銷毀的時候觸發(fā)
  10. destroyed()
  11. renderError(h, err){return h('div', {}, err.stack)} -> render()報錯時會調(diào)用此方法, 只會在開發(fā)環(huán)境調(diào)用, 只管自己的組件的錯誤, 不能冒泡
  12. errorCaptured () {} -> 可以捕捉到子組件的報錯, 用法類似renderError() 可以在線上使用
    調(diào)用一次的: create類, mount類, destroy類
    ssr調(diào)用的: create類
    生命周期中vue實例有哪些區(qū)別? -> $el會有所不同

注: 在使用.vue開始方式, 都沒有template, vue-loader會直接將.vue文件中的template解析成render()方法, 這樣更快

  • vue的數(shù)據(jù)綁定

  1. class的數(shù)據(jù)綁定
:class="{active: isActive}" -> 如果isActive是true就添加active的類名
:class="['header', {active: isActive}, isActive ? 'red' : 'green']" 
  1. style的數(shù)據(jù)綁定: 動態(tài)綁定的style會自動添加瀏覽器前綴
:style="[s1, s2, {color: 'red'}]"
data () {return { s1, s2 }}
  • computed和watch

  1. computed是vue的計算屬性, 可以對data進行處理, 擁有緩存機制, 只有當相關(guān)數(shù)據(jù)改變的時候, 才會執(zhí)行computed里的相關(guān)函數(shù), 這也是為什么要用computed而不是在methods創(chuàng)建一個方法

computed寫在標簽上時候, 不用加(), 這是因為, computed是通過Object.defineProperty(obj, 'abc', { get: () => xxx, value: xxx }), 通過get方法可以直接以變量名的方式調(diào)用函數(shù)

{
  computed: {
    name () {
      return first + last
    }
  }
}
// computed內(nèi)部支持Object.defineProperty()的get和set函數(shù)
{
  computed: {
    name: {
      get () {},
      set (name) {在這里可以改變data中的數(shù)據(jù)(不推薦, 容易搞出死循環(huán))}
    }
  }
}
  1. watch: 監(jiān)聽數(shù)據(jù)的變化, 當數(shù)據(jù)變化時才執(zhí)行這個watch里的方法
watch: {
  first (newData, oldData) {
     console.log('change', newData, oldData)
  }
}

// watch可以通過設置參數(shù)去立刻執(zhí)行

在data里聲明對象時, 有幾個坑, 1. 如果為聲明對象的屬性, 那么只有第一次給obj屬性賦值時會觸發(fā)watch, 2. 即便在data里聲明了obj.a,通過obj.a的方式修改數(shù)據(jù), 也不會觸發(fā)watch監(jiān)聽, watch只會監(jiān)聽obj的對象引用, 通過this.obj = {a:1}的方式才能被watch監(jiān)聽到,

watch: {
    // obj: {
    //   handler (newData, oldData) {
    //     console.log('obj.a change')
    //   },
    //   immediate: true // 立即執(zhí)行watch
    //   deep: true // 為true時候, watch會遞歸循環(huán)obj里的說有屬性, 性能低
    // }
    // 這種方式可以監(jiān)聽obj的屬性, 性能高用字符串里去寫對象的深入調(diào)用
    'obj.a': () => {
      console.log('obj.a change')
    }
  }
  • vue原生指令

指令修飾符: @click.stop: 組織冒泡, @keydown.13: 按回車, v-model.number="": 輸入的數(shù)字為number類型, v-model.trim="": 輸入的內(nèi)容清除前后空格, @touchend.capture=""或@touchstart.capture="": 事件捕獲

  1. v-text: 顯示文本, 標簽只能顯示v-text里的內(nèi)容
  2. v-html: 顯示未轉(zhuǎn)義的內(nèi)容, 可以解析標簽
  3. v-show: 原理display:none
  4. v-if: 節(jié)點不放在dom流里, 動態(tài)增刪節(jié)點, 性能低重繪
  5. v-for: 遍歷數(shù)組和對象, 性能優(yōu)化添加:key="內(nèi)容不要index" -> 通過:key里邊的內(nèi)容(唯一的id)去判斷是否重新渲染這一行:數(shù)組: v-for="(item, index) in items", 對象: v-for-"(val, key, index) in obj"
  6. v-on: 簡寫@: 綁定事件, 如果是dom節(jié)點:使用addEventListener, 如果是組件使用$on, 修飾符: .stop組織冒泡
  7. v-bind:簡寫: :綁定變量
  8. v-model: 表單響應式的改變數(shù)據(jù), 修飾符 .number: 數(shù)字為Number類型, .lazy: blur時顯示數(shù)據(jù), .trim: 清除前后空格
    -- checkbox的v-model綁定一個變量, 只要這個變量為true就是選中狀態(tài), 2. 可以對多個checkbox使用數(shù)組, 每一個checkbox的value就是這數(shù)組對應的值
    -- radio: v-model綁定的變量和radio的value相等時, 為選中狀態(tài)
  9. v-once: {{}}只執(zhí)行一次, 之后就不會檢測
  10. v-pre: 直接輸出{{}}和里邊的內(nèi)容
  • 組件的定義

  1. 全局定義: Vue.component('ComP', component1)
  2. 組件內(nèi)定義子組件: components: { ComP: component1 }
  3. props: 指定子組件的可配置行為
props: ['active', 'data']
props: {
  active: {
    type: Boolean,
    default: false,
    required: true
  },
  data: {
    type: [String, Number]
  }
}
// props的自定義核驗
props: {
  active: {
    // type: Boolean,
    validator (value) {
       return typeof value === Boolean
    }
  }
}
  • 組件的extend => 擴展vue,兩種extend方式,

-- 第一種, 實例化擴展: 類似于子組件, 可以通過 propsData傳遞props, 鉤子函數(shù)先調(diào)用, component里的, data會覆蓋component里的

const compVue = Vue.extend(component)
new CompVue({
  el: '#root', 
  propsData: {
    prop1: 'xxx'
  }
})

-- 第二種在組件內(nèi)的extends屬性中什么要繼承的組件

extends: component

如何去用呢? 在一個比較完善的組件里, 配置項太多, 或者還需要擴展, 這時候, 就可以在你的組件上extends這個組件, 然后去覆蓋或拓展他的配置

  • 組件的高級屬性

  1. slot插槽:
    -- 具名插槽:
const component = {
  template = '<div>
      <slot name="header"></slot>
      <slot></slot>
    </div>'
}
new Vue({
  components: { ComP: component},
  template: '
    <com-p>
      <p slot="header">我是header</p>
      <p>我是默認的插槽</p>
    </com-p>
  '
})

-- 插槽傳值

const component = {
  template = '<div>
      <slot name="header"></slot>
      <slot :a="aaa" b="bbb"></slot>
    </div>',
  data () {
    return {
      a: 'a的值'
    }
  }
}
new Vue({
  components: { ComP: component},
  template: '
    // 組件的ref是組件的實例(不推薦, 應該使用props), dom幾點的ref是dom節(jié)點
    <com-p ref="comp">
      <p slot="header" ref="p">我是header</p>
      <p scope-slot="obj">{{obj.a}}我是默認的插槽{{obj.b}}</p>
    </com-p>
  '
})
  1. provideinject: 往任意后代組件傳值, provide原生不支持reactive的, 需要用到Object.defineProperty()方法
const sunCom = {
  inject: ['yeye', 'data'],
  template: `<div>我是孫子</div>`,
  mounted () {
    console.log(this.$parent.$options.name)  // er-com
     console.log(this.yeye, this.data.value) // 
  }
}
const erCom = {
  name: 'er-com',
  components: {sunCom},
  template: `<sun-com></sun-com>`
}
new Vue({
  // provide必須是一個函數(shù), 否則this實例不會出現(xiàn)的
  provide () {
    // 官方不推薦, 有可能會改變寫法或棄用
    // 通過defineProperty()自己指定一個get方法
    const data = {}
    // 解釋一下下邊的代碼: 每次獲取 value的時候, 都會直接調(diào)用get()方法, 設置為可枚舉后, get方法就會每次獲取最新的數(shù)據(jù)
    // vue的reactive基礎就是Object.defineProperty()里的get()方法
    Object.defineProperty(data, 'value', {
      get: () => this.value,
      enumerable: true // 把屬性設置成可枚舉的, (可遍歷)
     })
    return {
       yeye: this,
       data
    }
  },
  components: {erCom},
  template: `<er-com><er-com>`,
  data: {
    value: 'yeye的value'
  }
})
  • vue之render()

{
  ...,
  render() {
    return this.$createElement('div', {標簽屬性}, 標簽內(nèi)容(還有標簽就在調(diào)用[$createElement)]多節(jié)點用數(shù)組)
  }
}
  • vue的原生組件:

-- <router-view>
-- <router-link>
-- <keep-alive>
-- <slot>
-- <transition>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祈远,隨后出現(xiàn)的幾起案子呆万,更是在濱河造成了極大的恐慌,老刑警劉巖车份,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谋减,死亡現(xiàn)場離奇詭異,居然都是意外死亡扫沼,警方通過查閱死者的電腦和手機出爹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門庄吼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人严就,你說我怎么就攤上這事总寻。” “怎么了梢为?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵渐行,是天一觀的道長。 經(jīng)常有香客問我铸董,道長祟印,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任粟害,我火速辦了婚禮蕴忆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘我磁。我一直安慰自己孽文,他們只是感情好,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布夺艰。 她就那樣靜靜地躺著芋哭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郁副。 梳的紋絲不亂的頭發(fā)上减牺,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音存谎,去河邊找鬼拔疚。 笑死,一個胖子當著我的面吹牛既荚,可吹牛的內(nèi)容都是我干的稚失。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼恰聘,長吁一口氣:“原來是場噩夢啊……” “哼句各!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晴叨,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凿宾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后兼蕊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體初厚,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年孙技,在試婚紗的時候發(fā)現(xiàn)自己被綠了产禾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片排作。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖下愈,靈堂內(nèi)的尸體忽然破棺而出纽绍,到底是詐尸還是另有隱情,我是刑警寧澤势似,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布拌夏,位于F島的核電站,受9級特大地震影響履因,放射性物質(zhì)發(fā)生泄漏障簿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一栅迄、第九天 我趴在偏房一處隱蔽的房頂上張望站故。 院中可真熱鬧,春花似錦毅舆、人聲如沸西篓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岂津。三九已至,卻和暖如春悦即,著一層夾襖步出監(jiān)牢的瞬間吮成,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工辜梳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粱甫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓作瞄,卻偏偏與公主長得像茶宵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宗挥,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

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

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容节预,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,052評論 0 29
  • 下載安裝搭建環(huán)境 可以選npm安裝属韧,或者簡單下載一個開發(fā)版的vue.js文件 瀏覽器打開加載有vue的文檔時,控制...
    冥冥2017閱讀 6,049評論 0 42
  • Vue 實例 屬性和方法 每個 Vue 實例都會代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,220評論 0 6
  • 定位文件位置:Ctrl+[+SAlt + Shift + F10:引用命名空間快捷鍵F7:查看代碼Shift F7...
    AsaGuo閱讀 2,434評論 0 0
  • 趕早六點的街道一派冷清蛤吓,趴在陋巷中的車子還在等著主人宵喂。早前熟悉的吆喝,現(xiàn)在七點才會有老板招呼会傲,勤勉不在人心不古啊锅棕。...
    叔謙閱讀 164評論 0 0