Abstract: Get started quickly to master the new features of Vue3 core The beta version of Vue3.0 has been available for some time, and the ...
Get started quickly to master the new features of Vue3 core
The beta version of Vue3.0 has been available for some time, and the official version is not far away, so I really need to learn the grammar of Vue3.0.
GitHub blog address: https://github.com/biaochenxuying/blog.
Environment building
$ git pull https://github.com/vuejs/vue-next.git
$ cd vue-next && yarn
When the download is complete, open the code and open sourceMap:
- Tsconfig.json modifies the sourceMap field to true:
"sourceMap": true
- Rollup.config.js in rollup.config.js, manually type:
output.sourcemap = true
- Generate a global file for vue:
yarn dev
- Create a demo directory in the root directory to store the sample code, create a html file in the demo directory, and introduce the built vue file
The use of api is very simple, the following content, look at the example code can understand, so the following examples will not explain too much.
Reactive
Reactive: creating responsive data objects.
The setup function is a new entry function, equivalent to beforeCreate and created in vue2.x, which is executed after beforeCreate and before created.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>reactive</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive } = Vue
const App = {
template: `
<button @click='click'>reverse</button>
<div style="margin-top: 20px">{{ state.message }}</div>
`,
setup() {
console.log('setup ');
const state = reactive({
message: 'Hello Vue3!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>
Ref & isRef
Ref: create a responsive data object isRef: check whether the value is a reference object for ref.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>ref & isRef</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef } = Vue
const App = {
template: `
<button @click='click'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const count = ref(0);
console.log("count.value:", count.value) // 0
count.value++
console.log("count.value:", count.value) // 1
// Judge whether a value is a response type
console.log('count is ref:', isRef(count))
click = () => {
count.value++;
console.log("click count.value:", count.value)
}
return {
count,
click,
}
}
}
createApp(App).mount('#app')
</script>
</html>
Template Refs
When using Composition API
,
the concepts of reactive reference and template reference are unified.
To get a reference to the element or component instance in the template,
we can declare ref
as usual and return from setup ()
.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Template Refs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs, onMounted, onBeforeUpdate } = Vue
const App = {
template: `
<button @click='click'>count++</button>
<div ref="count" style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const count = ref(null);
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(count.value) // <div/>
})
click = () => {
count.value++;
console.log("click count.value:", count.value)
}
return {
count,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Template Refs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs, onMounted, onBeforeUpdate } = Vue
const App = {
template: `
<div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
{{ item }}
</div>
`,
setup() {
const list = reactive([1, 2, 3])
const divs = ref([])
// make sure to reset the refs before each update
onBeforeUpdate(() => {
divs.value = []
})
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(divs.value) // [<div/>]
})
return {
list,
divs
}
}
}
createApp(App).mount('#app')
</script>
</html>
ToRefs
ToRefs: convert a responsive data object to a single responsive object.
Flatten a reactive
proxy object and convert it to a ref
proxy object,
so that the properties of the object can be used directly on the template
.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>toRefs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs } = Vue
const App = {
// template: `
// <button @click='click'>reverse</button>
// <div style="margin-top: 20px">{{ state.message }}</div>
// `,
// setup() {
// const state = reactive({
// message: 'Hello Vue3.0!!'
// })
// click = () => {
// state.message = state.message.split('').reverse().join('')
// console.log('state.message: ', state.message)
// }
// return {
// state,
// click
// }
// }
template: `
<button @click='click'>count++</button>
<div style="margin-top: 20px">{{ message }}</div>
`,
setup() {
const state = reactive({
message: 'Hello Vue3.0!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
console.log('state.message: ', state.message)
}
return {
click,
...toRefs(state)
}
}
}
createApp(App).mount('#app')
</script>
</html>
Computed
Computed: creating calculation properties.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>computed</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, computed } = Vue
const App = {
template: `
<button @click='handleClick'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const refData = ref(0);
const count = computed(()=>{
return refData.value;
})
const handleClick = () =>{
refData.value += 1 // To modify the dependency of count refData
}
console.log("refData:" , refData)
return {
count,
handleClick
}
}
}
createApp(App).mount('#app')
</script>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>computed</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, computed } = Vue
const App = {
template: `
<button @click='handleClick'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const refData = ref(0);
const count = computed({
get(){
return refData.value;
},
set(value){
console.log("value:", value)
refData.value = value;
}
})
const handleClick = () =>{
count.value += 1 // directly modify count
}
console.log(refData)
return {
count,
handleClick
}
}
}
createApp(App).mount('#app')
</script>
</html>
Watch & watchEffect
Watch: create watch snooping.
WatchEffect: if the responsive property changes, this function will be triggered.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>watch && watchEffect</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, watch, watchEffect } = Vue
const App = {
template: `
<div class="container">
<button style="margin-left: 10px" @click="handleClick()">button</button>
<button style="margin-left: 10px" @click="handleStop">Stop watch</button>
<button style="margin-left: 10px" @click="handleStopWatchEffect">Stop watchEffect</button>
<div style="margin-top: 20px">{{ refData }}</div>
</div>`
,
setup() {
let refData = ref(0);
const handleClick = () =>{
refData.value += 1
}
const stop = watch(refData, (val, oldVal) => {
console.log('watch ', refData.value)
})
const stopWatchEffect = watchEffect(() => {
console.log('watchEffect ', refData.value)
})
const handleStop = () =>{
stop()
}
const handleStopWatchEffect = () =>{
stopWatchEffect()
}
return {
refData,
handleClick,
handleStop,
handleStopWatchEffect
}
}
}
createApp(App).mount('#app')
</script>
</html>
V-model
V-model: bidirectional binding.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>v-model</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, watchEffect } = Vue
const App = {
template: `<button @click='click'>reverse</button>
<div></div>
<input v-model="state.message" style="margin-top: 20px" />
<div style="margin-top: 20px">{{ state.message }}</div>`,
setup() {
const state = reactive({
message:'Hello Vue 3!!'
})
watchEffect(() => {
console.log('state change ', state.message)
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>
Readonly
Using the readonly
function, you can return normal object
objects,
reactive
objects,
and ref
objects to a read-only object.
The returned readonly
object,
once modified, will have a warning
warning in console
.
The program will run as usual and will not report an error.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>readonly</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, readonly, watchEffect } = Vue
const App = {
template: `
<button @click='click'>reverse</button>
<button @click='clickReadonly' style="margin-left: 20px">readonly++</button>
<div style="margin-top: 20px">{{ original.count }}</div>
`,
setup() {
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// works for reactivity tracking
console.log(copy.count)
})
click = () => {
// mutating original will trigger watchers relying on the copy
original.count++
}
clickReadonly = () => {
// mutating the copy will fail and result in a warning
copy.count++ // warning!
}
return {
original,
click,
clickReadonly
}
}
}
createApp(App).mount('#app')
</script>
</html>
Provide & inject
provide
and inject
enable dependency injection similar to the 2.x provide
/ inject
option.
Both can only be called during the current active instance of setup()
.
import { provide, inject } from 'vue'
const ThemeSymbol = Symbol()
const Ancestor = {
setup() {
provide(ThemeSymbol, 'dark')
}
}
const Descendent = {
setup() {
const theme = inject(ThemeSymbol, 'light' /* optional default value */)
return {
theme
}
}
}
inject
accepts the optional default value as the second parameter.
If no default value is provided and the property cannot be found in the Provide
context, inject
returns undefined
.
Lifecycle Hooks
Comparison of life cycle hooks between Vue2 and Vue3:
Vue2 | Vue3 |
beforeCreate | setup(replace) |
created | setup(replace) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
/ | onRenderTracked |
/ | onRenderTriggered |
In addition to 2. x lifecycle equivalents,
the Composition API
also provides the following debugging hooks:
onRenderTracked
onRenderTriggered
Both hooks receive a DebuggerEvent
,
onTrack
and onTrigger
similar to observers:
export default {
onRenderTriggered(e) {
debugger
// inspect which dependency is causing the component to re-render
}
}
Example:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Lifecycle Hooks</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, onMounted, onUpdated, onUnmounted } = Vue
const App = {
template: `
<div class="container">
<button @click='click'>reverse</button>
<div style="margin-top: 20px">{{ state.message }}</div>
</div>`
,
setup() {
console.log('setup!')
const state = reactive({
message: 'Hello Vue3!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>
Last
This article only lists the api,Vue3.0 that the author thinks will be used a lot,
and there are many new features in it, such as customRef
,
markRaw
.
If readers are interested,
you can read the Vue Composition API documentation.
Vue Composition API documents: https://composition-api.vuejs.org/api.html#setup
Vue-next address: https://github.com/vuejs/vue-next