1. 程式人生 > 其它 >GitHub上標星13k的《Java面試突擊版》,分享面經

GitHub上標星13k的《Java面試突擊版》,分享面經

一:Vue基礎

1:vue生命週期和生命週期鉤子函式?

beforecreated:在例項初始化之後,el 和 data 並未初始化(這個時期,this變數還不能使用,在data下的資料,和methods下的方法,watcher中的事件都不能獲得到;)
created:完成了 data 資料的初始化,el沒有(這個時候可以操作vue例項中的資料和各種方法,但是還不能對"dom"節點進行操作;)
beforeMount:完成了 el 和 data 初始化這裡的el是虛擬的dom;
mounted :完成掛載,在這發起後端請求,拿回資料,配合路由鉤子做一些事情(掛載完畢,這時dom節點被渲染到文件內,一些需要dom的操作在此時才能正常進行),定義定時器
beforeUpdate

資料是新的,但是頁面是舊的
update:資料和頁面保持同步了,
beforeDestory: 你確認刪除定時器嗎?
destoryed :當前元件已被刪除,(其實就是頁面的退出)

A、什麼是vue生命週期?
Vue 例項從建立到銷燬的過程,就是生命週期。也就是從開始建立、初始化資料、編譯模板、掛載Dom→渲染、更新→渲染、解除安裝等一系列過程,我們稱這是 Vue 的生命週期。
B、vue生命週期的作用是什麼?
它的生命週期有多個事件鉤子,讓我們在控制整個Vue例項的過程時更容易形成好的邏輯。
C、vue生命週期總共有幾個階段?
它可以總共分為8個階段:建立前/後, 載入前/後,更新前/後,銷燬前/銷燬後
D、第一次頁面載入會觸發哪幾個鉤子?


第一次頁面載入時會觸發 beforeCreate, created, beforeMount, mounted 這幾個鉤子
E、DOM 渲染在 哪個週期中就已經完成?
DOM 渲染在 mounted 中就已經完成了。
F、簡單描述每個週期具體適合哪些場景?

1.beforecreate:可以在加個loading事件,在載入例項是觸發
2.created:初始化完成時的事件寫在這裡,如在這結束loading事件,非同步請求也適宜在這裡呼叫
3.mounted:非同步請求,啟動定時器,繫結自定義事件,訂閱訊息
4.updated:如果對資料統一處理
5.beforeDestroy:清除定時器,解綁自定義事件,取消訂閱,一般不再這裡在操作資料,即使操作了,頁面也不會更新了

2:v-show與v-if的區別

v-show是css切換,v-if是完整的銷燬和重新建立
使用頻繁切換時用v-show,執行時較少改變時用v-if
V-if=’false’v-if是條件渲染,當false的時候不會渲染
使用v-if的時候,如果值為false,那麼頁面將不會有這個html標籤生成
v-show則是不管值是為true還是false,html元素都會存在,只是css中的display顯示或隱藏
v-show 僅僅控制元素的顯示方式,將 display 屬性在 block 和 none 來回切換;而v-if會控制這個 DOM 節點的存在與否。當我們需要經常切換某個元素的顯示/隱藏時,使用v-show會更加節省效能上的開銷;當只需要一次顯示或隱藏時,使用v-if更加合理。

3:開發中常用的指令有哪些?

v-model:一般用在表達輸入,很輕鬆的實現表單控制元件和資料的雙向繫結

v-html:更新元素的innerHTML

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

var vm = new Vue({
            el : "#app",
            data : {
                msg : "<h1>這是一個h1元素內容</h1>"
            }
        });

v-show與v-if:條件渲染,注意二者區別
v-on:click:可以簡寫為@click,@繫結一個事件。如果事件觸發了,就可以指定事件的處理函式
v-for:基於源資料多次渲染元素或模板
v-bind:當表示式的值改變時,將其產生的連帶影響,響應式地作用於DOM語法
v-bind:title=”msg”簡寫: :title="msg"

v-clock解決頁面閃爍問題

如果網速慢,而該標籤內容是變數沒有請求響應回來的時候,頁面上先不顯示該標籤(vue給該標籤加了css樣式),當響應回來的時候改標籤預設將css樣式去除。此指令可以解決使用插值表示式頁面閃爍問題

將該指令加在html標籤中時,可以在該檔案中加style屬性為display:none,例子如下:

<div class="#app" v-cloak>
    <p>{{name}}</p>
</div>

[v-cloak] {
    display: none;
}

4:繫結class的陣列用法

1.物件方法v-bind:class="{'orange':isRipe, 'green':isNotRipe}”

:class="tindex == index ? 'aaa':'bbb'"

2.陣列方法v-bind:class="[class1,class2]"


3.行內v-bind:style="{color:color,fontSize:fontSize+'px'}”

5:計算屬性和methods

computed:{
    fullName:{
        //get有什麼作用? 當有人讀取例項(data)上的資料時候,get就會被呼叫,返回值可以是data上的值
        //get什麼時候呼叫? 1.初次讀取時,2.所依賴的資料發生變化的時候
        get(){  //fullName被讀取時呼叫
            return this.firstName
        },
        //set什麼時候呼叫? 當fullName被修改時
        set(value){	//fullName被修改時呼叫 
            	//非必須寫
            console.log('修改fullName後的值',value)	
        }
    }
    //簡寫方式
    fullNamejianxie(){
        return this.firstName  + 'jianxie'
    }
}

1.定義:要用的屬性存在,要通過已有的屬性計算而來
2.計算屬性的底層藉助Object.defineProperty()方法提供gettter/setter
3.get函式什麼時候呼叫?
     (1).初次讀取時
	 (2).所依賴的資料發生變化的時
4.優勢:與methods實現相比,內部有快取機制(複用),效率更高,除錯方便
5.備註:
	 (1).計算屬性最終會出現在vm(例項)上,直接讀取即可
	 (2).如果計算屬性被修改,那必須寫set去響應資料,且set中要引起計算時依賴的資料傳送變化

6:computed(計算屬性)和watch(監聽)的對比

computed

computed是計算屬性,也就是計算值,它更多用於計算值的場景
computed具有快取性,computed的值在getter執行後是會快取的,只有在它依賴的屬性值改變之後,下一次獲取computed的值時重新呼叫對應的getter來計算
computed適用於計算比較消耗效能的計算場景

watch

<template>
    <div class="container">
        <!-- 1.監聽例項上的基礎資料型別 -->
        <button @click="isHot = !isHot">{{isHot}}</button>

        <hr>

        <!-- 2.監聽引用型別的資料 -->
        <button @click="obj.age++">{{obj.age}}</button>
        
        <hr>

        <!-- 3.修改物件型別的資料變成字串 -->
        <button @click="obj = '變成其他資料型別了'">{{obj}}</button>
    </div>
</template>
<script>
    export default {
        name: 'index',
        data() {
            return {
                isHot : true,
                obj :{
                    name: 'js',
                    age : 18
                }   
            }
        },
        watch:{
            isHot:{
                immediate : true, //初始化的時候,讓handler呼叫一下
                handler(newValue,oldValue){ //handle什麼時候呼叫? isHot傳送變化時候
                    console.log('isHot被修改了',newValue,oldValue)
                }
            },
            // 'obj.age' :{ 
            //      handler(newValue,oldValue){ 
            //         console.log('age被修改了',newValue,oldValue)
            //     }
            //      //監視多級結構中某個屬性的變化(不建議這麼寫,如果有很多個值呢?)
            // },
            // obj:{
            //     //這麼寫即使是age的值傳送改變,也不會有任何操作。
            //     //因為此時監視的是 obj下的整個物件,除非物件變成其他型別的資料才會觸發
            //     handler(newValue,oldValue){ 
            //         console.log('obj被修改了',newValue,oldValue)
            //     }
            // },
            obj:{
                //深度監視 
                //不管是obj的資料型別變了,還是裡面的值變了
                deep : true,
                handler(newValue,oldValue){
                      console.log('obj被修改了',newValue,oldValue)
                }
            },
            // 簡寫方式 =>
            // 什麼時候的時候才能簡寫?   只需要用到handler的時候
            isHot(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue)  
            }
        }
    }
</script>
<style lang="less">
        .container{
            width: 100VW;
            height: 100VH;
        }
</style>


1.watch可以監聽非同步任務,計算屬性無法開啟非同步任務
<template>
  <div class="container">
    <button @click="obj = '變成其他資料型別了'">{{ obj }}</button>
    <div>
      {{ ahhh }}
    </div>
  </div>
</template>
<script>
export default {
  name: "index",
  data() {
    return {
      ahhh: 1,
      obj: {
        name: "js",
        age: 18,
      },
    };
  },
  watch: {
    obj: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("obj被修改了", newValue, oldValue);
        setTimeout(() => {  
            //這裡注意要用箭頭函式(this會一層一層往外找),不能使用普通函式(this執行windows)
            //開啟非同步任務
          console.log("this", this);
          this.ahhh += 1;
        }, 1000);
      },
    },
  },
};
</script>
<style lang="less">
.container {
  width: 100vw;
  height: 100vh;
}
</style>

7:vue元件的scoped屬性的作用

在style標籤上新增scoped屬性,以表示它的樣式作用於當下的模組,很好的實現了樣式私有化的目的;
但是也得慎用:樣式不易(可)修改,而很多時候,我們是需要對公共元件的樣式做微調的;

解決辦法:

①:使用混合型的css樣式:(混合使用全域性跟本地的樣式) <style> /* 全域性樣式 */ </style><style scoped> /* 本地樣式 */ </style>
②:深度作用選擇器(>>>)如果你希望 scoped 樣式中的一個選擇器能夠作用得“更深”,例如影響子元件,你可以使用 >>> 操作符:
<style scoped>
    .a >>> .b { /* ... */ } </style>

8:vue常用修飾符

修飾符分為:一般修飾符,事件修身符,按鍵、系統

①一般修飾符
.lazy:v-model 在每次 input 事件觸發後將輸入框的值與資料進行同步 。你可以新增 lazy 修飾符,從而轉變為使用 change 事件進行同步

<input v-model.lazy="msg" > 

.number

<input v-model.number="age" type="number">

.trim

1.如果要自動過濾使用者輸入的首尾空白字元 <input v-model.trim='trim'>

② 事件修飾符

1. 阻止單擊事件繼續傳播 
<a v-on:click.stop="doThis"></a>  

2.提交事件不再過載頁面
<form v-on:submit.prevent="onSubmit"></form> 

3.新增事件監聽器時使用事件捕獲模式(即元素自身觸發的事件先在此處處理,然後才交由內部元素進行處理)
<div v-on:click.capture="doThis">...</div>   

4.只當在 event.target 是當前元素自身時觸發處理函式(即事件不是從內部元素觸發的)
<div v-on:click.self="doThat">...</div> 

5.點選事件將只會觸發一次 
<a v-on:click.once="doThis"></a>  

6.vue元件新增事件
<Tabber @click.native="doThis"></Tabbar> 

7.修飾符可以串聯
<a v-on:click.stop.prevent="doThat"></a> 

③按鍵修飾符

全部的按鍵別名:

.enter
.tab
.delete (捕獲“刪除”和“退格”鍵)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
<input v-on:keyup.enter="submit"> 或者 <input @keyup.enter="submit">

④系統修飾鍵 (可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器)

.ctrl
.alt
.shift
.meta
<input @keyup.alt.67="clear"> 或者 <div @click.ctrl="doSomething">Do something</div><!-- Ctrl + Click -->

9:v-on可以監聽多個事件處理嗎?(可以的)

一個元素繫結多個事件的兩種寫法,一個事件繫結多個函式的兩種寫法,修飾符的使用。

<a style="cursor:default" v-on='{click:DoSomething,mouseleave:MouseLeave}'>doSomething</a>

在method方法裡面分別寫兩個事件;

<button @click="a(),b()">點我ab</button>

10:vue事件中使用event物件

<template>
    //不加括號的的時候,直接拿到event物件
<button @click="btn">點選</button>  
</template>

btn(value){
    console.log('value',value)	
}



//現在的需求是點選事件直接傳值過來,但是也要event物件
<template>
    //加了括號
<button @click="btn($event,1,2)">點選</button>  
</template>

btn(value,...a){
    console.log('value',value)
    console.log('a',a)  // [1,2]
}

11:nextTick

  1. 語法:this.$nextTick(回撥函式)
  2. 作用:在下一次 DOM 更新結束後執行其指定的回撥。
  3. 什麼時候用:當改變資料後,要基於更新後的新DOM進行某些操作時,要在nextTick所指定的回撥函式中執行。
**比如你想讓一個dom元素顯示**,然後下一步去獲取這個元素的offsetWidth,最後你獲取到的會是0。
openSubmenu() {
    this.show = true //獲取不到寬度
    this.$nextTick(() => 
      //這裡才可以 let w = this.$refs.submenu.offsetWidth;
   })
}

13:Vue元件間傳遞資料的方式

1.props配置項(父傳子 or 子傳父)

  1. 功能:讓元件接收外部傳過來的資料

  2. 傳遞資料:<Demo name="xxx"/>

  3. 接收資料:

    1. 第一種方式(只接收):props:['name']

    2. 第二種方式(限制類型):props:{name:String}

    3. 第三種方式(限制類型、限制必要性、指定預設值):

      props:{
      	name:{
      	type:String, //型別
      	required:true, //必要性
      	default:'老王' //預設值
      	}
      }
      

    備註:props是隻讀的,Vue底層會監測你對props的修改,如果進行了修改,就會發出警告,若業務需求確實需要修改,那麼請複製props的內容到data中一份,然後去修改data中的資料。

2.元件的自定義事件(子傳父)

  1. 一種元件間通訊的方式,適用於:子元件 ===> 父元件

  2. 使用場景:A是父元件,B是子元件,B想給A傳資料,那麼就要在A中給B繫結自定義事件(事件的回撥在A中)。

  3. 繫結自定義事件:

    1. 第一種方式,在父元件中:<Demo @dataarr="test"/><Demo v-on:dataarr="test"/>

    2. 第二種方式,在父元件中:

      <Demo ref="demo"/>
      ......
      mounted(){
         this.$refs.xxx.$on('dataarr',this.test)
      }
      
    3. 若想讓自定義事件只能觸發一次,可以使用once修飾符,或$once方法。

  4. 觸發自定義事件:this.$emit('dataarr',資料)

  5. 解綁自定義事件this.$off('dataarr')

  6. 元件上也可以繫結原生DOM事件,需要使用native修飾符。

  7. 注意:通過this.$refs.xxx.$on('dataarr',回撥)繫結自定義事件時,回撥要麼配置在methods中要麼用箭頭函式,否則this指向會出問題!

3.全域性事件匯流排(GlobalEventBus)

  1. 一種元件間通訊的方式,適用於任意元件間通訊

  2. 安裝全域性事件匯流排:

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //安裝全域性事件匯流排,$bus就是當前應用的vm
    	},
        ......
    }) 
    
  3. 使用事件匯流排:

    1. 接收資料:A元件想接收資料,則在A元件中給$bus繫結自定義事件,事件的回撥留在A元件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. 提供資料:this.$bus.$emit('xxxx',資料)

  4. 最好在beforeDestroy鉤子中,用$off去解綁當前元件所用到的事件。

4.訊息訂閱與釋出(pubsub)

  1. 一種元件間通訊的方式,適用於任意元件間通訊

  2. 使用步驟:

    1. 安裝pubsub:npm i pubsub-js

    2. 引入: import pubsub from 'pubsub-js'

    3. 接收資料:A元件想接收資料,則在A元件中訂閱訊息,訂閱的回撥留在A元件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.pid = pubsub.subscribe('xxx',this.demo) //訂閱訊息
      }
      
    4. 提供資料:pubsub.publish('xxx',資料)

    5. 最好在beforeDestroy鉤子中,用PubSub.unsubscribe(pid)取消訂閱。

//父元件需要拿到子元件的資料和例項
父元件呼叫子元件的方法 :this.$refs.yeluosen.childMethod()

//子元件拿到父元件的例項 (可以處理父元件分資料和呼叫父元件的方法)
 this.$parent

14:vue更新響應式的缺陷和$set的使用

<template>
  <div class="container">
    <ul>
      <li v-for="(item, index) in person" :key="index">
        {{ item }}
      </li>
    </ul>
    <button @click="addsex">手動點選給物件新增屬性</button>

    <hr />

    <ul>
      <li v-for="(item, index) in hobby" :key="index">
        {{ item }}
      </li>
    </ul>
    <button @click="addhobby">手動點選給陣列修改屬性</button>

  </div>
</template>
<script>
export default {
  name: "index",
  data() {
    return {
      person: {
        name: "jack",
        age: 18,
      },
      hobby: ["抽菸", "喝酒", "燙頭"],
      persons: [
        { name: "gsq", age: 18 ,status : false },
        { name: "gsq02", age: 19,status : false },
        { name: "gsq03", age: 20,status : false },
      ],
    };
  },
  methods: {
    addsex() {
      // 物件不能這麼新增
      // this.person.sex = '男'

      //正確寫法
      this.$set(this.person, "sex", "男")
    },
    addhobby(){
      // 必須使用響應式的陣列方法可以更新/或者使用this.$set
      // 哪些陣列是相應式的?
      // push,pop,shift,unshift,splice,sort,reverse
        // this.hobby.splice(0,1,'哈哈')

      // 或者使用
      this.$set(this.hobby,0,'哈哈')  
    }
  },
};
</script>
<style lang="less">
.container {
  width: 100vw;
  height: 100vh;
}
</style>


Vue監視資料的原理:
1. vue會監視data中所有層次的資料。

2. 如何監測物件中的資料?
通過setter實現監視,且要在new Vue時就傳入要監測的資料。
	(1).物件中後追加的屬性,Vue預設不做響應式處理
	(2).如需給後新增的屬性做響應式,請使用如下API:
		Vue.set(target,propertyName/index,value) 或 
		vm.$set(target,propertyName/index,value)

3. 如何監測陣列中的資料?
通過包裹陣列更新元素的方法實現,本質就是做了兩件事:
	(1).呼叫原生對應的方法對陣列進行更新。
	(2).重新解析模板,進而更新頁面。

4.在Vue修改陣列中的某個元素一定要用如下方法:
	1.使用這些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
	2.Vue.set() 或 vm.$set()

特別注意:Vue.set() 和 vm.$set() 不能給vm 或 vm的根資料物件 新增屬性!!!

15:Vue獲取dom元素節點並操作元素的樣式

$refs 獲取的是元件物件
$el 獲取的是dom節點

1.獲取到元素節點(這裡通過this.$refs獲取元素節點)
this.$refs.xxxxx.$el
2.操作元素的樣式
this.$refs.num1Underline.$el.style.transform = 'scaleX(1)'

這種方法需要注意的是$el 用於獲取vue掛載的例項的dom物件,如果不新增$el則獲取不到style的屬性值,會列印 TypeError: Cannot read property 'style' of undefined 錯誤,這個錯誤大家一定都很熟悉,是型別錯誤,沒有訪問到dom元素

16:forceUpdate

//資料更新後,元件沒更新。使用這個方法強制重新整理元件
this.$forceUpdate();

17:mixin(混入)

1. 功能:可以把多個元件共用的配置提取成一個混入物件

2. 使用方式:

   第一步定義混合:

{
data(){....},
methods:{....}
....
}

第二步使用混入:

​	全域性混入:```Vue.mixin(xxx)```
​	區域性混入:```mixins:['xxx']	```

18:外掛

1. 功能:用於增強Vue

2. 本質:包含install方法的一個物件,install的第一個引數是Vue,第二個以後的引數是外掛使用者傳遞的資料。

3. 定義外掛:
   物件.install = function (Vue, options) {
       // 1. 新增全域性過濾器
       Vue.filter(....)
   
       // 2. 新增全域性指令
       Vue.directive(....)
   
       // 3. 配置全域性混入(合)
       Vue.mixin(....)
   
       // 4. 新增例項方法
       Vue.prototype.$myMethod = function () {...}
       Vue.prototype.$myProperty = xxxx
   }

4. 使用外掛:Vue.use()

19:插槽

  1. 作用:讓父元件可以向子元件指定位置插入html結構,也是一種元件間通訊的方式,適用於 父元件 ===> 子元件

  2. 分類:預設插槽、具名插槽、作用域插槽

  3. 使用方式:

    1. 預設插槽:

      父元件中:
              <Category>
                 <div>html結構1</div>
              </Category>
      子元件中:
              <template>
                  <div>
                     <!-- 定義插槽 -->
                     <slot>插槽預設內容...</slot>
                  </div>
              </template>
      
    2. 具名插槽:

      父元件中:
              <Category>
                  <template slot="center">
                    <div>html結構1</div>
                  </template>
      
                  <template v-slot:footer>
                     <div>html結構2</div>
                  </template>
              </Category>
      子元件中:
              <template>
                  <div>
                     <!-- 定義插槽 -->
                     <slot name="center">插槽預設內容...</slot>
                     <slot name="footer">插槽預設內容...</slot>
                  </div>
              </template>
      
    3. 作用域插槽:

      1. 理解:資料在元件的自身,但根據資料生成的結構需要元件的使用者來決定。(games資料在Category元件中,但使用資料所遍歷出來的結構由App元件決定)

      2. 具體編碼:

        父元件中:
        		<Category>
        			<template scope="scopeData">
        				<!-- 生成的是ul列表 -->
        				<ul>
        					<li v-for="g in scopeData.games" :key="g">{{g}}</li>
        				</ul>
        			</template>
        		</Category>
        
        		<Category>
        			<template slot-scope="scopeData">
        				<!-- 生成的是h4標題 -->
        				<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
        			</template>
        		</Category>
        子元件中:
                <template>
                    <div>
                        <slot :games="games"></slot>
                    </div>
                </template>
        		
                <script>
                    export default {
                        name:'Category',
                        props:['title'],
                        //資料在子元件自身
                        data() {
                            return {
                                games:['紅色警戒','穿越火線','勁舞團','超級瑪麗']
                            }
                        },
                    }
                </script>
        

二:Vue-Router

1.基本使用

  1. 安裝vue-router,命令:npm i vue-router

  2. 應用外掛:Vue.use(VueRouter)

  3. 編寫router配置項:

    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入Luyou 元件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //建立router例項物件,去管理一組一組的路由規則
    const router = new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
    //暴露router
    export default router
    
  4. 實現切換(active-class可配置高亮樣式)

    <router-link active-class="active" to="/about">About</router-link>
    
  5. 指定展示位置

    <router-view></router-view>
    

2.幾個注意點

  1. 路由元件通常存放在pages資料夾,一般元件通常存放在components資料夾。
  2. 通過切換,“隱藏”了的路由元件,預設是被銷燬掉的,需要的時候再去掛載。
  3. 每個元件都有自己的$route屬性,裡面儲存著自己的路由資訊。
  4. 整個應用只有一個router,可以通過元件的$router屬性獲取到。

3.多級路由(多級路由)

  1. 配置路由規則,使用children配置項:

    routes:[
    	{
    		path:'/about',
    		component:About,
    	},
    	{
    		path:'/home',
    		component:Home,
    		children:[ //通過children配置子級路由
    			{
    				path:'news', //此處一定不要寫:/news
    				component:News
    			},
    			{
    				path:'message',//此處一定不要寫:/message
    				component:Message
    			}
    		]
    	}
    ]
    
  2. 跳轉(要寫完整路徑):

    <router-link to="/home/news">News</router-link>
    

4.路由的query引數

  1. 傳遞引數

    <!-- 跳轉並攜帶query引數,to的字串寫法 -->
    <router-link :to="/home/message/detail?id=666&title=你好">跳轉</router-link>
    				
    <!-- 跳轉並攜帶query引數,to的物件寫法 -->
    <router-link 
    	:to="{
    		path:'/home/message/detail',
    		query:{
    		   id:666,
                title:'你好'
    		}
    	}"
    >跳轉</router-link>
    
  2. 接收引數:

    $route.query.id
    $route.query.title
    

5.命名路由

  1. 作用:可以簡化路由的跳轉。

  2. 如何使用

    1. 給路由命名:

      {
      	path:'/demo',
      	component:Demo,
      	children:[
      		{
      			path:'test',
      			component:Test,
      			children:[
      				{
                          name:'hello' //給路由命名
      					path:'welcome',
      					component:Hello,
      				}
      			]
      		}
      	]
      }
      
    2. 簡化跳轉:

      <!--簡化前,需要寫完整的路徑 -->
      <router-link to="/demo/test/welcome">跳轉</router-link>
      
      <!--簡化後,直接通過名字跳轉 -->
      <router-link :to="{name:'hello'}">跳轉</router-link>
      
      <!--簡化寫法配合傳遞引數 -->
      <router-link 
      	:to="{
      		name:'hello',
      		query:{
      		   id:666,
                  title:'你好'
      		}
      	}"
      >跳轉</router-link>
      

6.路由的params引數

  1. 配置路由,宣告接收params引數

    {
    	path:'/home',
    	component:Home,
    	children:[
    		{
    			path:'news',
    			component:News
    		},
    		{
    			component:Message,
    			children:[
    				{
    					name:'xiangqing',
    					path:'detail/:id/:title', //使用佔位符宣告接收params引數
    					component:Detail
    				}
    			]
    		}
    	]
    }
    
  2. 傳遞引數

    <!-- 跳轉並攜帶params引數,to的字串寫法 -->
    <router-link :to="/home/message/detail/666/你好">跳轉</router-link>
    				
    <!-- 跳轉並攜帶params引數,to的物件寫法 -->
    <router-link 
    	:to="{
    		name:'xiangqing',
    		params:{
    		   id:666,
                title:'你好'
    		}
    	}"
    >跳轉</router-link>
    

    特別注意:路由攜帶params引數時,若使用to的物件寫法,則不能使用path配置項,必須使用name配置!

  3. 接收引數:

    $route.params.id
    $route.params.title
    

7.路由的props配置

​ 作用:讓路由元件更方便的收到引數

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一種寫法:props值為物件,該物件中所有的key-value的組合最終都會通過props傳給Detail元件
	// props:{a:900}

	//第二種寫法:props值為布林值,布林值為true,則把路由收到的所有params引數通過props傳給Detail元件
	// props:true
	
	//第三種寫法:props值為函式,該函式返回的物件中每一組key-value都會通過props傳給Detail元件
	props(route){
		return {
			id:route.query.id,
			title:route.query.title
		}
	}
}

8.<router-link>的replace屬性

  1. 作用:控制路由跳轉時操作瀏覽器歷史記錄的模式
  2. 瀏覽器的歷史記錄有兩種寫入方式:分別為pushreplacepush是追加歷史記錄,replace是替換當前記錄。路由跳轉時候預設為push
  3. 如何開啟replace模式:<router-link replace .......>News</router-link>

9.程式設計式路由導航

  1. 作用:不借助<router-link> 實現路由跳轉,讓路由跳轉更加靈活

  2. 具體編碼:

    //$router的兩個API
    this.$router.push({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}
    })
    
    this.$router.replace({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}
    })
    this.$router.forward() //前進
    this.$router.back() //後退
    this.$router.go() //可前進也可後退
    

10.快取路由元件

  1. 作用:讓不展示的路由元件保持掛載,不被銷燬。

  2. 具體編碼:

    <keep-alive include="News"> 
        <router-view></router-view>
    </keep-alive>
    

11.兩個新的生命週期鉤子

  1. 作用:路由元件所獨有的兩個鉤子,用於捕獲路由元件的啟用狀態。

  2. 具體名字:

    1. activated路由元件被啟用時觸發。
    2. deactivated路由元件失活時觸發。

    keep-alive 是 Vue 內建的一個元件,可以使被包含的元件保留狀態,或避免重新渲染。

    <keep-alive>
      <component>
        <!-- 該元件將被快取! -->
      </component>
    </keep-alive>
    如果只想 router-view 裡面某個元件被快取
    
    
    export default [
      {
        path: '/',
        name: 'home',
        component: Home,
        meta: {
          keepAlive: true // 需要被快取
        }
      }, {
        path: '/:id',
        name: 'edit',
        component: Edit,
        meta: {
          keepAlive: false // 不需要被快取
        }
      }
    ]
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive">
            <!-- 這裡是會被快取的檢視元件,比如 Home! -->
        </router-view>
    </keep-alive>
     
    <router-view v-if="!$route.meta.keepAlive">
        <!-- 這裡是不被快取的檢視元件,比如 Edit! -->
    </router-view>
    

12.路由守衛

  1. 作用:對路由進行許可權控制

  2. 分類:全域性守衛、獨享守衛、元件內守衛

  3. 全域性守衛:

    //全域性前置守衛:初始化時執行、每次路由切換前執行
    router.beforeEach((to,from,next)=>{
    	console.log('beforeEach',to,from)
    	if(to.meta.isAuth){ //判斷當前路由是否需要進行許可權控制
    		if(localStorage.getItem('school') === 'atguigu'){ //許可權控制的具體規則
    			next() //放行
    		}else{
    			alert('暫無許可權檢視')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next() //放行
    	}
    })
    
    //全域性後置守衛:初始化時執行、每次路由切換後執行
    router.afterEach((to,from)=>{
    	console.log('afterEach',to,from)
    	if(to.meta.title){ 
    		document.title = to.meta.title //修改網頁的title
    	}else{
    		document.title = 'vue_test'
    	}
    })
    
  4. 獨享守衛:

    beforeEnter(to,from,next){
    	console.log('beforeEnter',to,from)
    	if(to.meta.isAuth){ //判斷當前路由是否需要進行許可權控制
    		if(localStorage.getItem('school') === 'atguigu'){
    			next()
    		}else{
    			alert('暫無許可權檢視')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next()
    	}
    }
    
  5. 元件內守衛:

    //進入守衛:通過路由規則,進入該元件時被呼叫
    beforeRouteEnter (to, from, next) {
    },
    //離開守衛:通過路由規則,離開該元件時被呼叫
    beforeRouteLeave (to, from, next) {
    }
    

13.vue-router實現路由懶載入( 動態載入路由 )

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import( '../views/Home.vue')   //使用import的方式匯入元件
  },
  {
    path: '/about',
    name: 'About',
    component: () => import( '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

14.vue-router如何響應 路由引數 的變化?

原來的元件例項會被複用。這也意味著元件的生命週期鉤子不會再被呼叫。你可以簡單地 watch (監測變化) $route 物件:

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 對路由變化作出響應...
    }
  }
}

15.$route和$router的區別是什麼

$route為當前router跳轉當前路由元件裡可獲取name、path、query、params等

$router為VueRouter例項,想要導航到不同URL,則使用$router.push方法

16.hash和history的區別

  1. 對於一個url來說,什麼是hash值?—— #及其後面的內容就是hash值。

  2. hash值不會包含在 HTTP 請求中,即:hash值不會帶給伺服器。

  3. hash模式:

    1. 地址中永遠帶著#號,不美觀 。
    2. 若以後將地址通過第三方手機app分享,若app校驗嚴格,則地址會被標記為不合法。
    3. 相容性較好。
  4. history模式:

    1. 地址乾淨,美觀 。
    2. 相容性和hash模式相比略差。
    3. 應用部署上線時需要後端人員支援,解決重新整理頁面服務端404的問題。

三:Vuex

1.概念

​ 在Vue中實現集中式狀態(資料)管理的一個Vue外掛,對vue應用中多個元件的共享狀態進行集中式的管理(讀/寫),也是一種元件間通訊的方式,且適用於任意元件間通訊。

2.何時使用?

​ 多個元件需要共享資料時,音樂播放、登入狀態、加入購物車

3.搭建vuex環境

  1. 建立檔案:src/store/index.js

    //引入Vue核心庫
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //應用Vuex外掛
    Vue.use(Vuex)
    
    //準備actions物件——響應元件中使用者的動作
    const actions = {}
    //準備mutations物件——修改state中的資料
    const mutations = {}
    //準備state物件——儲存具體的資料
    const state = {}
    
    //建立並暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state
    })
    
  2. main.js中建立vm時傳入store配置項

    ......
    //引入store
    import store from './store'
    ......
    
    //建立vm
    new Vue({
    	el:'#app',
    	render: h => h(App),
    	store
    })
    

4.基本使用

  1. 初始化資料、配置actions、配置mutations,操作檔案store.js

    //引入Vue核心庫
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引用Vuex
    Vue.use(Vuex)
    
    const actions = {
        //響應元件中加的動作
    	jia(context,value){
    		// console.log('actions中的jia被呼叫了',miniStore,value)
    		context.commit('JIA',value)
    	},
    }
    
    const mutations = {
        //執行加
    	JIA(state,value){
    		// console.log('mutations中的JIA被呼叫了',state,value)
    		state.sum += value
    	}
    }
    
    //初始化資料
    const state = {
       sum:0
    }
    
    //建立並暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    })
    
  2. 元件中讀取vuex中的資料:$store.state.sum

  3. 元件中修改vuex中的資料:$store.dispatch('action中的方法名',資料)$store.commit('mutations中的方法名',資料)

    備註:若沒有網路請求或其他業務邏輯,元件中也可以越過actions,即不寫dispatch,直接編寫commit

5.getters的使用

  1. 概念:當state中的資料需要經過加工後再使用時,可以使用getters加工。

  2. store.js中追加getters配置

    ......
    
    const getters = {
    	bigSum(state){
    		return state.sum * 10
    	}
    }
    
    //建立並暴露store
    export default new Vuex.Store({
    	......
    	getters
    })
    
  3. 元件中讀取資料:$store.getters.bigSum

6.四個map方法的使用

  1. mapState方法:用於幫助我們對映state中的資料為計算屬性

    computed: {
        //藉助mapState生成計算屬性:sum、school、subject(物件寫法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //藉助mapState生成計算屬性:sum、school、subject(陣列寫法)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters方法:用於幫助我們對映getters中的資料為計算屬性

    computed: {
        //藉助mapGetters生成計算屬性:bigSum(物件寫法)
        ...mapGetters({bigSum:'bigSum'}),
    
        //藉助mapGetters生成計算屬性:bigSum(陣列寫法)
        ...mapGetters(['bigSum'])
    },
    
  3. mapActions方法:用於幫助我們生成與actions對話的方法,即:包含$store.dispatch(xxx)的函式

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(物件形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(陣列形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  4. mapMutations方法:用於幫助我們生成與mutations對話的方法,即:包含$store.commit(xxx)的函式

    methods:{
        //靠mapActions生成:increment、decrement(物件形式)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        
        //靠mapMutations生成:JIA、JIAN(物件形式)
        ...mapMutations(['JIA','JIAN']),
    }
    

備註:mapActions與mapMutations使用時,若需要傳遞引數需要:在模板中繫結事件時傳遞好引數,否則引數是事件物件。

7.模組化+名稱空間

  1. 目的:讓程式碼更好維護,讓多種資料分類更加明確。

  2. 修改store.js

    const countAbout = {
      namespaced:true,//開啟名稱空間
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//開啟名稱空間
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
    
  3. 開啟名稱空間後,元件中讀取state資料:

    //方式一:自己直接讀取
    this.$store.state.personAbout.list
    //方式二:藉助mapState讀取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. 開啟名稱空間後,元件中讀取getters資料:

    //方式一:自己直接讀取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:藉助mapGetters讀取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. 開啟名稱空間後,元件中呼叫dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:藉助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 開啟名稱空間後,元件中呼叫commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:藉助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

2:Vuex state資料的雙向繫結

// 在從元件的computed中
computed: {
    user: {
        get() {
          return this.$store.state.user
        },
        set(v) {
          // 使用vuex中的mutations中定義好的方法來改變
          this.$store.commit('USER', v)
        }
    }<br>}<br>// 在元件中就可以使用
     
        
        
<input v-modle="user" />        

四:Vue中的開發經驗

1:搭建Vue腳手架(vue-cli)並建立一個專案

1.安裝node.js環境
	  [官網下載地址](https://nodejs.org/en/download/)
               一路安裝完成後 開啟cmd  
               輸入 node -v
               輸入 npm -v
               如果能看到node和npm的版本號了,說明已經安裝成功

               
               
2.安裝vue-cli
               有npm和cnpm兩種方式,網上都說cnpm好些,所以我也用的cnpm安裝,
               首先利用淘寶映象安裝cnpm      
               npm install cnpm -g --registry=https://registry.npm.taobao.org       
               安裝完成
               輸入 cnpm -v
  
               
               
3.然後全域性安裝 vue-cli
               輸入指令 cnpm install -g vue-cli
               這個命令只需要執行一次就可以了。安裝上之後,以後就不用安裝了。
               檢視vue版本號
               vue -V    //注:V是大寫字母V

               如果提示“無法識別 ‘vue’ ” ,有可能是 npm 版本過低,需要手動更新npm的版本號,這也是上面說的為什麼要保證npm版本號高的原因,npm的版本可以手動升級更新,沒記錯的話應該是               
               npm install -g npm
               
 
               
               
4.使用vue-cli來建立一個基於 webpack 模板的新專案               
               建立
               cmd利用cd指令進入到儲存專案的資料夾下,然後輸入命令           
               輸入 vue init webpack

5.安裝專案所需要的依賴               
   				進入新建的專案資料夾下,就是上頭有一些檔案的裡面,輸入命令
                輸入 指令 cnpm install

6.執行專案
               根據你package.json裡的配置裡的指令
               一般情況下都是 npm run dev
               
7.打包資源上線
               根據你package.json裡的配置裡的指令
               一般情況下都是 npm run build
              	 
8.具體建立專案 部落格地址
               https://www.cnblogs.com/coober/p/10875647.html
               

2:關於不同版本的Vue

  1. vue.js與vue.runtime.xxx.js的區別:
    1. vue.js是完整版的Vue,包含:核心功能 + 模板解析器。
    2. vue.runtime.xxx.js是執行版的Vue,只包含:核心功能;沒有模板解析器。
  2. 因為vue.runtime.xxx.js沒有模板解析器,所以不能使用template這個配置項,需要使用render函式接收到的createElement函式去指定具體內容。

3:vue.config.js配置檔案

  1. 使用vue inspect > output.js可以檢視到Vue腳手架的預設配置。
  2. 使用vue.config.js可以對腳手架進行個性化定製,詳情見:https://cli.vuejs.org/zh

2:vue中如何編寫可複用的元件?

①建立元件頁面eg Toast.vue;
②用Vue.extend()擴充套件一個元件構造器,再通過例項化元件構造器,就可創造出可複用的元件
③將toast元件掛載到新建立的div上;
④把toast元件的dom新增到body裡;
⑤修改優化達到動態控制頁面顯示文字跟顯示時間;

import Vue from 'vue'; 
import Toast from '@/components/Toast';     //引入元件
let ToastConstructor  = Vue.extend(Toast) // 返回一個“擴充套件例項構造器”
 
let myToast = (text,duration)=>{
    let toastDom = new ToastConstructor({
        el:document.createElement('div')    //將toast元件掛載到新建立的div上
    })
    document.body.appendChild( toastDom.$el )   //把toast元件的dom新增到body裡
    
    toastDom.text = text;
    toastDom.duration = duration;
 
    // 在指定 duration 之後讓 toast消失
    setTimeout(()=>{
        toastDom.isShow = false;  
    }, toastDom.duration);
}
export default myToast;

點選檢視 https://blog.csdn.net/qq_38563845/article/details/77524934

3:vue父元件向子元件傳物件,不實時更新解決

思路1:就是讓利用v-if的重新渲染機制

1.首先考慮的就是手動刷了,給元件加個v-if=”someShow“;

//  這是元件上寫法 :<my-component v-if="someShow"></my-component>
 
// 下邊寫在父元件的methods裡
refesh:function(){
	this.someShow=false;
	var _this=this;
	this.$nextTick(function(){
		_this.someShow = true;
	})
  
}
// $nextTick
// $nextTick 是在下次 DOM 更新迴圈結束之後執行延遲迴調,在修改資料之後使用 $nextTick,則可以在回撥中獲取更新後的 DOM  這樣重新渲染就會是最新資料了




思路2:利用watch監聽

在子元件中監聽你要的資料,當然別監聽物件,監聽了不一定好使。親測不好使,測過好使的,可以給我留言。


data:function(){
    return {
        title:"",
        content:"",
        btn:""
    }
},   
methods:{
        changeTitle:function(){
            this.title=this.listTitle;
            // 這裡的每次變化了就複製給元件上的變數,檢視也就更改了			
        },
        changeList:function(){
            this.content=this.listList;
        },
        changeBtn:function(){
            this.btn=this.listBtn;
        }
    },
watch:{
    	listTitle:"changeTitle",
        listList:"changeList",
        listBtn:"changeBtn"
        // 冒號前邊這個就是從父元件傳過來的,後邊的就是變化了的監聽函式
}

4:is的用法(用於動態元件且基於 DOM 內模板的限制來工作。)

is用來動態切換元件,DOM模板解析

<table> <tr is="my-row"></tr> </table>

5:vue腳手架配置代理

方法一

​ 在vue.config.js中新增如下配置:

devServer:{
  proxy:"http://localhost:5000"
}

說明:

  1. 優點:配置簡單,請求資源時直接發給前端(8080)即可。
  2. 缺點:不能配置多個代理,不能靈活的控制請求是否走代理。
  3. 工作方式:若按照上述配置代理,當請求了前端不存在的資源時,那麼該請求會轉發給伺服器 (優先匹配前端資源)

方法二

​ 編寫vue.config.js配置具體代理規則:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'開頭的請求路徑
        target: 'http://localhost:5000',// 代理目標的基礎路徑
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'開頭的請求路徑
        target: 'http://localhost:5001',// 代理目標的基礎路徑
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin設定為true時,伺服器收到的請求頭中的host為:localhost:5000
   changeOrigin設定為false時,伺服器收到的請求頭中的host為:localhost:8080
   changeOrigin預設值為true
*/

說明:

  1. 優點:可以配置多個代理,且可以靈活的控制請求是否走代理。
  2. 缺點:配置略微繁瑣,請求資源時必須加字首。

五:Vue原始碼原理

1:vue.js2.x的兩個核心是什麼(資料驅動、元件系統。)

資料驅動:Object.defineProperty和儲存器屬性: getter和setter(所以只相容IE9及以上版本),可稱為基於依賴收集的觀測機制,核心是VM,即ViewModel,保證資料和檢視的一致性。

            let number = 18
            let person = {
                name : 'jack',
                sex : '男'
            }

            Object.defineProperty(person,'age',{
                // value : 18,
                // enumerable : true, //控制熟悉是否可以列舉,預設值是false
                // writable : true, //控制熟悉是否可以被修改,預設值是false
                // configurable : true, //控制屬性是否可以被刪除,預設值是false

                //當有人讀取person的age屬性時,get函式(getter)就會被呼叫,且返回值就是age的值
                get(){
                    console.log('有人讀取了age')
                    return number
                },

                //當有人修改person的age屬性時,set函式(setter)就會被呼叫,且會收到修改的具體值
                set(value){
                    console.log(`有人修改了age,值為:${value}`)
                    number = value
                }

            })

元件系統:

2:VUE資料代理的原理

通過一個物件代理對另一個物件中的屬性的操作(讀寫)
let obj = {x:100}
let obj2 = {y:200}

Object.defineProperty(obj2,'x',{
    get(){
        return obj.x
    },
    set(){
        obj.x = value
    }
})


1.Vue中的資料代理:
	通過vm物件代理data物件中的資料(讀/寫)
2.Vue中資料代理的好處:
	更加方便的操作data中的資料
3.基本原理
	通過Object.defineProperty()把data物件中所有屬性新增到vm上
    為每一個新增到vm上的屬性,都指定一個getter/setter
	在getter/setter內部去操作(讀/寫)data中對應的屬性

3:Vue 元件中 data 為什麼必須是函式

vue元件中data值不能為物件,因為物件是引用型別,元件可能會被多個例項同時引用。
如果data值為物件,將導致多個例項共享一個物件,其中一個元件改變data屬性值,其它例項也會受到影響。

4:Vue雙向繫結的原理

5:Vue的diff演算法(列表渲染key的作用和原理)

1.虛擬DOM中key的作用:
key是虛擬DOM物件的標識,當狀態中的資料發生變化時,Vue會根據【新資料】生成【新的虛擬DOM】
隨後,Vue進行【新的虛擬DOM】與【舊的虛擬DOM】的差異比較,比較規則如下

2.對比規則:
(1).舊虛擬DOM中找到了與新虛擬DOM相同的key:
	1.若虛擬DOM中的內容沒變,直接使用之前的真實DOM!
    2.若虛擬DOM中的內容變了,則生成新的真實DOM,隨後替換掉頁面中之前的真實DOM
(2).舊虛擬DOM中未找到與新虛擬DOM相同的key
	1.建立新的真實DOM,隨後渲染到頁面

3.用index作為key可能會引發的問題:
	1.若對資料進行,逆序新增,逆序刪除等破壞順尋操作:
    	會產生沒有必要的真實DOM更新 => 介面效果沒問題,但是效率低
	2.如果結構中還有包含輸入類的DOM:
    	會產生錯誤DOM更新 => 介面有問題

4.開發中如何選擇key?:
	1.最好使用每條資料的唯一標識作為key,比如id,手機號,身份證號,學號等唯一值
	2.如果不存在對資料的逆序新增,逆序刪除等破壞性順序操作,僅用於渲染列表展示,使用index作為key是沒問題的

6:Vue是怎麼檢測資料的改變的原理

let data = {
    name :'jack',
    age : 18
}

//建立一個監視的例項物件,用於監視data中屬性的變化
const obs = new Observer(data)

//準備一個vm例項物件
let vm = {}
vm._data = data = obs

function Observer(obj){
    //彙總物件中所有屬性形成的陣列
    const keys = Object.keys(obj)
    //遍歷
    keys.forEach((k)=>{
        Object.defineProperty(this,k,{
            get(){
                return obj[k]
            },
            set(val){
                console.log(`${k}被改了,我要去解析模板了,生成虛擬DOM`)
                obj[k] = val
            }
        })
    })
}  
//自己實現的基本的原理,只是對第一層的基本資料型別進行檢測。無法檢測到裡面的

Vue的底層對data中的物件資料檢測進行了遞迴,所以都能檢測到,
數組裡的物件資料沒有檢測

六:對Vue的理解

1:談談對MVVM的理解

M-model,model代表資料模型,也可以在model中定義資料修改和操作的業務邏輯

V-view,view代表UI元件,它負責將資料模型轉化為UI展現出來

VM-viewmodel,viewmodel監聽模型資料的改變和控制檢視行為、處理使用者互動,簡單理解就是一個同步view和model的物件,連線model和view

2:vue是漸進式的框架的理解:(主張最少,沒有多做職責之外的事)

Vue的核心的功能,是一個檢視模板引擎,但這不是說Vue就不能成為一個框架。如下圖所示,這裡包含了Vue的所有部件,在宣告式渲染(檢視模板引擎)的基礎上,我們可以通過新增元件系統、客戶端路由、大規模狀態管理來構建一個完整的框架。更重要的是,這些功能相互獨立,你可以在核心功能的基礎上任意選用其他的部件,不一定要全部整合在一起。可以看到,所說的“漸進式”,其實就是Vue的使用方式,同時也體現了Vue的設計的理念
在我看來,漸進式代表的含義是:主張最少。檢視模板引擎
每個框架都不可避免會有自己的一些特點,從而會對使用者有一定的要求,這些要求就是主張,主張有強有弱,它的強勢程度會影響在業務開發中的使用方式。
比如說,Angular,它兩個版本都是強主張的,如果你用它,必須接受以下東西:
必須使用它的模組機制- 必須使用它的依賴注入- 必須使用它的特殊形式定義元件(這一點每個檢視框架都有,難以避免)
所以Angular是帶有比較強的排它性的,如果你的應用不是從頭開始,而是要不斷考慮是否跟其他東西整合,這些主張會帶來一些困擾。
Vue可能有些方面是不如React,不如Angular,但它是漸進的,沒有強主張,你可以在原有大系統的上面,把一兩個元件改用它實現,當jQuery用;也可以整個用它全家桶開發,當Angular用;還可以用它的檢視,搭配你自己設計的整個下層用。也可以函式式,都可以,它只是個輕量檢視而已,只做了自己該做的事,沒有做不該做的事,僅此而已。
漸進式的含義,我的理解是:沒有多做職責之外的事。

3:vue等單頁面應用及其優缺點

缺點:

不支援低版本的瀏覽器,最低只支援到IE9;
不利於SEO的優化(如果要支援SEO,建議通過服務端來進行渲染元件);
第一次載入首頁耗時相對長一些;
不可以使用瀏覽器的導航按鈕需要自行實現前進、後退。

優點:

無重新整理體驗,提升了使用者體驗;
前端開發不再以頁面為單位,更多地採用元件化的思想,程式碼結構和組織方式更加規範化,便於修改和調整;
API 共享,同一套後端程式程式碼不用修改就可以用於Web介面、手機、平板等多種客戶端
使用者體驗好、快,內容的改變不需要重新載入整個頁面。

七:Vue3擴充套件

1.VUE3簡介

  • 2020年9月18日,Vue.js釋出3.0版本,代號 One Piece(海賊王)

2.Vue3帶來了什麼

1.效能的提升

1.打包大小減少41%
2.初次渲染快55%,更新渲染快33%
3.記憶體減少54%   
...    

2.原始碼的升級

使用Proxy代替defineProperty實現響應式
重寫虛擬DOM的實現和Tree-Shaking
...

3.擁抱TypeScript

Vue3可以更好的支援TypeScript

4.新的特性

1.Composition API(組合API)
	steup配置
    ref與reactive
    watch與watchEffect
    provide與inject
    ...
2.新的內建元件
	Fragment
    Teleport
    Suspense
3.其他改變
	新的生命週期鉤子
    data選項應始終被宣告為一個函式
    移除keyCode支援作為v-on的修飾符
    ...

3.建立Vue3.0工程

1.使用vue-cli建立

## 檢視@vue/cli版本,確保@vue/cli版本在4.5.0以上
vue --version  或者 vue -V
## 安裝或者升級你的@vue/cli
npm install -g @vue/cli
## 建立
vue create vue-text   /或者使用 node自帶的(如果升級不了@vue/cli)    npx @vue/cli create my-app
## 啟動
cd vue-text
npm run serve

2.使用vite建立

## 什麼是vite?   
新一代前端構建工具
## 優勢
1.開發環境中,無需打包操作,可快速的冷啟動
2.輕量快速的熱過載(HMR)
3.真正的按需編譯,不再等待整個應用編譯完成
## 建立工程
npm init  vite-app <project-name>
## 進入工程目錄
cd <project-name>
## 安裝依賴
npm install
## 執行
npm run dev

4.常用Composition API

1.拉開序幕額setup

1.理解:vue3.0中的一個新的配置項。值為一個函式
2.setups是所有Composition API(組合api) “表演的舞臺”
3.元件中所有用到的:資料,方法等等。均要配置在setup中
4.setup函式的兩種返回值:
	1.若返回一個物件,則物件中的屬性,方法,在模板中直接使用
    2.若返回畫一個渲染函式,則可以自定義渲染內容(瞭解即可)
5.注意點
	1.儘量不要與Vue2.x配置混用
	2.但在setup中不能訪問到Vue2.x配置(data,methsds,computed...)
	3.如果重名,setup優先
    

2.ref函式

1.作用:定義一個響應式的資料
2.語法 : const xxx = ref(initValue)
	1.建立一個響應式的資料的引用物件
    2.js操作資料
    3.模板中讀取資料:不需要  .value  直接 <div>{{xxx}}<div/>
3.備註:
	1.接收資料可以是基本型別,也可以是物件型別
    2.基本型別的資料:響應式依然是靠Object.defineProperty() 的get和set
    3.物件型別的資料: 內部求助了Vue3.0中的一個新的函式  - reactive

3.reactive

1.作用:定義一個物件型別的響應式資料(基本類型別用它,用ref函式)
2.語法 const 代理物件  = reactive(被代理物件)接收一個物件或者陣列,返回一個代理器物件(proxy物件)
3.reactive定義的響應資料是深層次的
4.內部基於ES6的proxy,通過代理物件對原資料內部資料都是響應式的