Vue 3.0 起手式

Milk Midi
7 min readJun 26, 2020

--

Vue3.0 beta 發佈了,
在正式推出前試玩一下,來看一下有什麼新寫法。

當然官方文件先整個看過一次
https://composition-api.vuejs.org/

最大的改變,就是推出 Composition API
寫起來有點像是 React hooks, 但又點不一樣
如果不想寫 Composition API, 也可以用 2.0 的寫法。

這篇就針對 Composition API 來討論

1 程式進入點只有一個 setup
要什麼功能,就 import {computed, onMouted} from ‘vue’
然後沒有 this 了 (寫起來真的有點像 react hooks)

import { reactive, computed } from 'vue';export default {
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2),
});
console.log(this); // 會得到 undefined
function increment() {
state.count += 1;
}
return {
state,
increment,
};
},
};

2 data 換成 reactive({})
如上方的 example, 透過 reactive 來建立 data
computed 也可以在這寫
methods 直接在 setup 寫 function, 最後 return 出去

3 ref
vue3.0 除了可以用 reactive 外,還是一個新的 ref 可以用
(跟 react 的 useRef 有點像)
那 ref 和 reactive 有什麼差,目前奶綠我還在深入研究這兩種寫法有什麼優缺點,不過可以先看一下這兩篇文章

https://composition-api.vuejs.org/#ref-vs-reactive

https://www.danvega.dev/blog/2020/02/12/vue3-ref-vs-reactive/

export default {
setup() {
const count:Ref<number> = ref(0);
const double = computed(() => count.value * 2);
function increment() {
count.value += 1;
}
return {
count,
double,
increment,
};
},
};

4 watch, watchEffect
watch:需指定要 watch 的變數
watchEffect:不需要,直接塞一個 function 進去
但不需要像 react hooks 加 dependencies, vue 會自動判斷,讚

import {
reactive, computed, watch, ref, watchEffect,
Ref,
} from 'vue';
export default {
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2),
});
const count2:Ref<number> = ref(2); // watch reactive
watch(() => state.count, (curr:number, prev:number) => {
console.log(`watch state.count curr:${curr}, prev${prev}`);
});
// watch ref
watch(count2, (curr:number, prev:number) => {
console.log(`watch count2 curr:${curr}, prev:${prev}`);
});
// 新的 api, 不需要像 react hooks 加 dependencies, vue 會自動判斷,讚
// https://composition-api.vuejs.org/api.html#watcheffect
watchEffect(() => {
// 這裡只 watch state.count, 所以 count2 更新時並不會發生 watch
console.log(`%cwatchEffect state.count:${state.count}`, 'background:#1abc9c');
// console.log(`watchEffect count2:${count2.value}`);
});
// methods
function increment() {
state.count += 1;
}
function incrementCount2() {
count2.value += 1;
}
return {
state,
count2,
increment,
incrementCount2,
};
},
};

5 LifeCycle
通通都需要 import

import {
onMounted, onUpdated, onUnmounted
} from 'vue';
export default {
setup() {
onMounted(() => {
console.log('onMounted');
});
onUpdated(() => {
console.log('onUpdated');
});
onUnmounted(() => {
console.log('onUnmounted');
});
return {
};
},
};

6 emit
setup 沒有 this, 那怎麼像 2.0 時用 this.$emit 呢
答案在 setup 的第二個參數。

import {
onMounted, onUpdated, onUnmounted,
} from 'vue';export default {
setup(props, {emit}) {
return {
};
},
};

7 程式進入點:
2.0 用 new Vue({}).$mount(‘#app’)
3.0 用

import { createApp } from 'vue';
import App from './App.vue';
createApp(App)
.mount('#app');

8 Composition API 最強大的功能
就是可以像 react hooks 一樣,把功能抽離出去
假設你有一隻 API, 在 vue mounted 時要被呼叫
那如果有 n 個 component 都要有一樣的功能呢?
2.0 時只能寫 mixin
3.0 就可以抽離出去

const useFetchData = ():UseFetchDataType => {
const state:UseFetchDataType = reactive({
userData: {},
isLoading: false,
});
onMounted(async () => {
state.isLoading = true;
const userData:UserData = await fetchData();
state.userData = userData;
state.isLoading = false;
});
return state;
};
export default useFetchData;

要用的 component 就可以這樣寫

export default {
setup() {
const state:UseFetchDataType = useFetchData();
return {
myVar: 'hi,9527',
state,
// ...state, 不能這樣寫 reactivity lost!
};
},
};
</script>

Vuex 和 Vue Router 目前還在研究中

最後再補奶綠我用 vue3.0 寫的 todolist ,祝大家學習愉快。
SourceCode

--

--