Vue3.0 _ scaffolding
The official website provides two build methods, one is vite, the other is VUE-CLI. This article uses the former Vite, mainly because it is faster to build. We execute the commands in turn:
npm init vite vue3-demo
cd vue3-demo
npm install
npm run dev
Copy the code
Vite +vue3: localhost:3000
Vue3.0 _ new features
First, the composite API(API) Composition
The purpose of a composite API is to group together code for the same logical concern, which enhances the legibility and maintainability of components without constantly jumping to and from blocks of options for related code while working on a single logical concern.
# setup
options
- Vue3 will
setup
As an entry point to the composite API, executed before component creation setup
The option is a function that takes two parameters, props and context- Everything it returns can be used for the rest of the component (lifecycle, computed properties, methods, and so on) as well as the template of the component
The setup structure looks like this:
export default { components: { }, props: { user: { type: String, required: true } }, setup(props) { console.log(props) // { user: } // exposes template Return {} // whatever is returned here can be used for the rest of the component} // the "rest" of the component}Copy the code
# ref
function
ref
Create a reactive reference to our value and return one{value: xxx}
The value of a reactive variable can be accessed or changed through the value property of the object- It is used in conjunction with the composite API
- from
setup
The returned ref is automatically shallow unpacked when accessed in the template and does not need to be used in the template.value
<template>
<div>{{ counter }}</div>
</template>
import { ref } from 'vue'
setup(){
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
return {
counter
}
}
Copy the code
# reactive
function
- Take an object, return a reactive copy of the object, and make a “deep” reactive transformation of the object
- You can unpack all the deep ones
refs
While maintaining the responsiveness of ref
Const count = ref(1) const obj = reactive({count}) console.log(obj.count === count.value) // true // it updates 'obj.count' count.value++ console.log(count.value) // 2 console.log(obj.count) // 2 // It also updates' count 'ref obj.count++ console.log(obj.count) // 3 console.log(count.value) // 3Copy the code
# toRefs
function
ToRefs can get a responsive reference to a prop in the props parameter of the setup option
import { watch, ToRefs} from 'vue' setup (props) {// Create a responsive reference to prop's 'user' property using 'toRefs' const {counter} = toRefs(props) watch(counter, (newValue, oldValue) => { console.log('The new counter value is: ' + counter.value) }) ... return { ... }}Copy the code
# addon
Prefix life cycle function
- Life cycles are nothing new, however with VUe3 we can write life cycle hooks in the setup option by prefixing them with on, for example
mounted
insetup
In a writtenonMounted
- add
on
The prefix’s lifecycle functions each accept a callback that is executed when the hook is called by the component
import { ref, onMounted } from 'vue' setup (props) { const repositories = ref([]) const getUserRepositories = async () => { Repositories. value = await fetchUserRepositories(props. User)} onMounted(Repositories.getUserRepositories) // `getUserRepositories` return { repositories, getUserRepositories } }Copy the code
# watch
Reactive changes to a function
The watch function exported from vue can take three arguments:
- A reactive reference or getter that you want to listen for
- A callback
- Optional configuration options
Import {ref, watch} from 'vue' const counter = ref(0) // Watch (counter, (newValue,) oldValue) => { console.log('The new counter value is: ' + counter.value) })Copy the code
When counter is modified, such as counte.value=5, listening triggers and executes the callback (the second argument). This is equivalent to the following code:
export default {
data() {
return {
counter: 0
}
},
watch: {
counter(newValue, oldValue) {
console.log('The new counter value is: ' + this.counter)
}
}
}
Copy the code
# watchEffect
function
- Reactive trace dependencies
- Automatic application and reapplication of secondary applications
- Automatic application: Execute a function passed in immediately
- Reapply side application: Rerun this function when dependent changes occur
- Automatically stops listening when a component is uninstalled
- Side effects are performed before component updates
onInvalidate
The function is used to remove side applicationsflush
Option to re-execute side applications after component updates
# independentcomputed
attribute
Computed output is a responsive reference
- Returns an immutable response
ref
object
const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // errorCopy the code
- Used to create writable
ref
object
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
Copy the code
# summary
The composite API can be summarized as follows: The logic in each logical concern (that is, a separate functional module) is extracted into a separate combinative function, each of which is composed of functions derived from vUE (REF, toRefs, Watch, computed, etc.), which are introduced into the component like building blocks. We can then gather all the contents (properties, methods, etc.) of these individual function modules in the component setup function and expose them to the rest of the component (lifecycle, computed properties, methods, etc.) and the template of the component in an API-like manner.
Second, the Teleport
Teleport literally means teleportation (objects, people); Remote, so it’s not hard to guess that it acts like slot, transferring/mounting/injecting components in templates
- There are two parameters
to
anddisabled
- It works by means of
to
Property mounts A component to A location in B that needs to be rendered, while A component’s logic is independent of B, keeping A component independent
<body> <div style="position: relative;" > <h3>Tooltips with Vue 3 Teleport</h3> <div> <modal-button></modal-button> </div> </div> </body>Copy the code
const app = Vue.createApp({});
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal!
</button>
<div v-if="modalOpen" class="modal">
<div>
I'm a modal!
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
`,
data() {
return {
modalOpen: false
}
}
})
Copy the code
As can be seen from the above example, Teleport is used to bind the button in the frame component to the trigger logic of the frame in one component. All you need to do is to specify the place to be mounted to, that is, the body of the target element. The target element can also be an ID or class query selector. Modal-button components can be rendered normally in the template, which is logically or structurally clean.
Segments of three,
Vue3 supports multiple root nodes within a component, which means that you don’t need to wrap a DOM tag under the template tag within the component
<! -- demo.vue --> <template> <header>... </header> <main v-bind="$attrs">... </main> <footer>... </footer> </templateCopy the code
Four,emits
options
In component eventsemits
1. The emits option defines the events that a component can fire to its parent
<template> <div> <p>{{ text }}</p> <button v-on:click="$emit('accepted')">OK</button> </div> </template> <script> export default { props: ['text'], emits: ['accepted'] } </script>Copy the code
2. Any event listeners not declared in emits are counted as native events in the component’s $attr and are bound by default to the component’s root node’s native event listener
<my-button V-on :click="handleClick"></my-button>Copy the code
</button V-on :click="$emit('click', $event)">OK</button> </template> <script> export default {emits: [] // do not declare events} </script>Copy the code
If the click event is not declared in the emits option, the event will be emitted twice:
- Once from the child component
$emit
- A native event listener from the root element
3. The emits option can accept an array or object that allows event validation to be configured (the validation function should return a Boolean value).
App.component ('custom-form', {emits: {// no validation click: null, // validate the event submit: ({ email, password }) => { if (email && password) { return true } else { console.warn('Invalid submit event payload! ') return false } } }, methods: { submitForm(email, password) { this.$emit('submit', { email, password }) } } })Copy the code
Five,v-model
The new usage
v-model
Parameter changes:vue2
In: on the componentv-model
usevalue
As the prop andinput
As the event
<ChildComponent v-model="pageTitle" /> <! <ChildComponent :value="pageTitle" @input="pageTitle = $event" />Copy the code
vue3
In: on the componentv-model
usemodelValue
As the prop andupdate:modelValue
As the event
<ChildComponent v-model="pageTitle" /> <! <ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle =" />Copy the code
- Multiple V-Model bindings can be used on the same component
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
Copy the code
- You can customize
v-model
The modifier- Vue3 used in
modelModifiers
Objects are custom modifiers, that isv-model
The modifier will passmodelModifiers
Prop provides components - When the component’s
created
When the lifecycle hook fires,modelModifiers
Prop will containcapitalize
And its value istrue
- Vue3 used in
Here’s an example of capitalizing a string whenever an input event is triggered by the element:
// html
<div id="app">
<my-component v-model.capitalize="myText"></my-component>
{{ myText }}
</div>
Copy the code
// vue
const app = Vue.createApp({
data() {
return {
myText: ''
}
}
})
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
created() {
console.log(this.modelModifiers) // { capitalize: true }
},
methods: {
emitValue(e) {
let value = e.target.value
if (this.modelModifiers.capitalize) { // true
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:modelValue', value)
}
},
template: `<input
type="text"
:value="modelValue"
@input="emitValue">`
})
app.mount('#app')
Copy the code