Vue3.0系列——「vue3.0學習手冊」第一期

Vam的金豆之路發表於2020-10-23

在這裡插入圖片描述

一、專案搭建

vite是尤大大開發的一款意圖取代webpack的工具。其實現原理是利用ES6的import傳送請求載入檔案的特性。攔截這些請求,做一些編譯,省去webpack冗長的打包時間。並將其與Rollup捆綁在一起用於生產。
在開發過程中沒有捆綁。原始碼中的ES Import語法直接提供給瀏覽器,瀏覽器通過本機<script module>支援對其進行解析,從而為每次匯入發出HTTP請求。開發伺服器攔截請求,並在必要時執行程式碼轉換。例如,對*.vue檔案的匯入會在傳送回瀏覽器之前即時進行編譯。

1、全域性安裝vite腳手架

npm install -g create-vite-app

2、使用腳手架建立專案

create-vite-app projectName

3、進入專案資料夾

cd projectName

4、安裝依賴

npm install

5、啟動vue3.0專案

npm run dev

二、vue2.x存在的問題

2.x中的一點問題是當業務不斷增多時,資料跟邏輯分散,會很難維護。

<template>
  <div>
    <div>
      <input type="text" v-model="obj.id">
      <input type="text" v-model="obj.con">
      <button @click="submit">提 交</button>
    </div>
    <ul>
      <li v-for="(item,index) in list" :key="item.id" @click="cli(index)">
        {{item.id}}-{{item.con}}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name:"filterBox",
  data(){
    return {
      list:[
        {
          id:1,
          con:"a"
        },
        {
          id:2,
          con:"b"
        }
      ],
      obj:{
        id:"",
        con:""
      }
      // 程式碼資料1
      // 程式碼資料2
      // ...
    }
  },
  methods:{
    cli(index){
      this.list = this.list.filter((item,idx)=>idx!==index);
      console.log(this.list);
    },
    submit(){
      // const obj = Object.assign({},this.obj);
      this.list.push(this.obj);
      this.obj.id = "";
      this.obj.con = "";
    },
    // 執行程式碼程式碼邏輯3
    // ...
  },
  computed:{
  	// 執行程式碼程式碼邏輯1
  },
  watch:{
   // 執行程式碼邏輯2
  }
}
</script>

<style>

</style>

三、組合API

ref

<template>
  <div>
    <p>{{count}}</p>
    <button @click="add">add</button>
  </div>
</template>

<script>
import {ref} from "vue"
export default {
  name: 'App',
  setup(){
    // 定義一個名稱叫做count變數,這個變數的初始值是0
    // 這個變數發生該改變之後,vue會自動更新頁面。
    const count  = ref(0);
	// 在組合API中,如果想定義方法,不用定義到methods中,直接在setup函式中定義即可。
    const add = () => {
      count.value+=1;
    }
	// 在組合API中定義的變數/方法,要想在外界使用,必須return出去。
    return {
      count,
      add
    }
  }
}
</script>

ref只能監聽簡單型別的變化,不能監聽複雜型別的變化(物件/陣列)。
它的本質是reactive,當我們給ref函式傳遞一個值時,ref函式會自動將ref轉換成reactive

ref(0) -->  reactive({
value:0
})

另外,需要注意的是,如果是通過ref建立出來的資料,那麼在template中使用的時候不用通過.value來獲取。因為Vue會自動給我們新增.value

那麼vue是如何決定是否需要自動新增.value的。vue在解析資料之前,會自動判斷這個資料是否是ref型別的,如果是就自動新增.value,如果不是就不自動新增.value

vue是如何判斷當前的資料是否是ref型別的?
通過當前資料的__v_ref來判斷的,如果有這個私有的屬性,並且取值為true,那麼就代表是一個ref型別的資料。

那麼我們開發者也有自己api來判斷。isRef(資料),返回true或者是false

import {isRef} from 'vue'

reactive

reactive 可以監聽複雜型別的變化,如物件或者陣列。

let state = reactive({
	name:"maomin"
});
// 或
let arr = reactive([1,2,3]);
<template>
  <div>
    <ul>
      <li v-for="(item,index) in state.list" :key="item.id" @click="removeItem(index)">{{item.id}}--{{item.con}}</li>
    </ul>
  </div>
</template>

<script>
import {reactive} from "vue"
export default {
  name: 'App',
  setup(){
    const state  = reactive({
      list:[
        {
          id:1,
          con:"A"
        },
        {
          id:2,
          con:"B"
        },
        {
          id:3,
          con:"C"
        }
      ]
    });

    const removeItem = (index) => {
      state.list = state.list.filter((item,i)=>i!==index)
    }

    return {
      state,
      removeItem
    }
  }
}
</script>

我們可以改變下,把資料跟邏輯放在一塊,這樣就解決了vue2.x的資料跟邏輯分散的問題。

<template>
  <div>
    <ul>
      <li
        v-for="(item, index) in state.list"
        :key="item.id"
        @click="removeItem(index)"
      >
        {{ item.id }}--{{ item.con }}
      </li>
    </ul>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    let {state,removeItem} = userReturn();
    return {
      state,
      removeItem,
    };
  },
};

function userReturn(params) {
  const state = reactive({
    list: [
      {
        id: 1,
        con: "A",
      },
      {
        id: 2,
        con: "B",
      },
      {
        id: 3,
        con: "C",
      },
    ],
  });

  const removeItem = (index) => {
    state.list = state.list.filter((item, i) => i !== index);
  };

  return {state,removeItem}
}
</script>

我們實現了上面的刪除功能,那我們在實現一個新增的功能。

<template>
  <div>
    <input type="text" v-model="state2.items.id">
    <input type="text" v-model="state2.items.con">
    <button @click="addItem">新增</button>
    <ul>
      <li
        v-for="(item, index) in state.list"
        :key="item.id"
        @click="removeItem(index)"
      >
        {{ item.id }}--{{ item.con }}
      </li>
    </ul>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    let {state,removeItem} = userRemove();
    let {state2,addItem} = userAdd(state);
    return {
      state,
      removeItem,
      state2,
      addItem
    };
  },
};
// 新增
function userAdd(state) {
   const state2 = reactive({
    items:{
      id:"",
      con:""
    }
  });

  const addItem = () => {
    const items = Object.assign({},state2.items);
    state.list.push(items);
    state2.items.id = "";
    state2.items.con = "";
  };

  return {state,state2,addItem}
}
// 刪除
function userRemove(params) {
  const state = reactive({
    list: [
      {
        id: 1,
        con: "A",
      },
      {
        id: 2,
        con: "B",
      },
      {
        id: 3,
        con: "C",
      },
    ],
  });

  const removeItem = (index) => {
    state.list = state.list.filter((item, i) => i !== index);
  };

  return {state,removeItem}
}
</script>

如果是其他物件,預設情況下修改物件,介面不會更新。

<template>
  <div>
    <p>{{state.time}}</p>
    <button @click="add">加一天</button>
  </div>
</template>

<script>
import {reactive} from 'vue'
export default {
  name:"Demo4",
  setup(){
    const state = reactive(
      {
        time:new Date()
      }
    );
    function add () {
      state.time.setDate(state.time.getDate()+1);
      console.log(state);
    }
    return {
      state,
      add
    }
  }
}
</script>

<style>

</style>

如果想更新,可以通過重新賦值的方法。

<template>
  <div>
    <p>{{ state.time }}</p>
    <button @click="add">加一天</button>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "Demo4",
  setup() {
    const state = reactive({
      time: new Date(),
    });
    function add() {
      const newTime = new Date(state.time.getTime());
      newTime.setDate(state.time.getDate() + 1);
      state.time = newTime;
      console.log(state);
    }
    return {
      state,
      add,
    };
  },
};
</script>

<style>
</style>

同樣,我們開發者如果要是檢測一個資料是否是reactive型別的。可以用isReactive(資料),返回true或者false

import {isReactive} from 'vue'

四、組合API本質

compositionAPIoptionAPI可以混合使用。其本質是注入。

<template>
  <div>
    <p>Vue2.x</p>
    <button @click="cli1">點選</button>
    <p>Vue3.0</p>
    <button @click="cli2">點選</button>
  </div>
</template>

<script>
import {ref} from "vue"
export default {
  name:"Demo2",
  data(){
    return {
      msg:"Vue2.x"
    }
  },
  methods:{
    cli1(){
      alert(this.msg);
    }
  },
  setup(){
    let txt = ref("Vue3.0"); // 注入到data函式內
    function cli2() { // 注入到methods屬性內
      alert(txt.value); 
    }
    return {
      txt,
      cli2
    }
  }
}
</script>

<style>

</style>

五、setup執行時機與注意事項

setup函式,是在beforecreate鉤子之前完成的。所以無法使用datamethods
另外要注意的是setup是同步的,不是非同步的。

<template>
  <div>
    <button @click="name">開啟</button>
  </div>
</template>

<script>
export default {
  name:"Demo3",
  data(){
    return {
      msg:"hello"
    }
  },
  setup(){
    function name() {
      console.log(this.msg); // undefined
    }
    return {
      name
    }
  }
}
</script>

<style>

</style>

下一期繼續

  • 歡迎關注我的公眾號前端歷劫之路

  • 回覆關鍵詞電子書,即可獲取12本前端熱門電子書。

  • 回覆關鍵詞紅寶書第4版,即可獲取最新《JavaScript高階程式設計》(第四版)電子書。

  • 關注公眾號後,點選下方選單即可加我微信,我拉攏了很多IT大佬,建立了一個技術交流、文章分享群,期待你的加入。

  • 作者:Vam的金豆之路

  • 微信公眾號:前端歷劫之路

Vue3.0系列——「vue3.0學習手冊」第一期

相關文章