Article Catalog
- What's New in Vue3
- I. Introduction to Vue3
- 1.1 State of Vue3
- 1.2 Basic use of vite
- 1.3 Creating a vue project
- 1.4 Combined API
- vue2 Options API Vue3 Combination API
- II. The setup function
- 2.1 Introduction to the setup function
- 2.2 Combined API-Life Cycle
- Attention:
- III. Vue component data
- 3.1 Introduction
- 3.2 Combining API-ref Functions
- 3.3 Combining API-reactive Functions
- 3.4 The toRef function
- 3.5 The toRefs function
- 3.6 Cases of knowledge utilization
- Encapsulation:
- 3.7 Supplementary: the ref attribute:
- IV. Computational properties and listeners
- 4.1 Calculation of properties
- Compute attribute bidirectional bindings:
- 4.2 The watch listener
- V. Communication between Vue components
- 5.1 Combined API - Parent-Child Communication
- lit. the son passes on to the father
- == Subcomponent: setup (props, {emit})==
- The parent component listens:
- Parameters of setup
- Parent component:
- Subcomponents:
- 5.2 Provide / Inject
- Provide data to descendants and also methods
- Summary:
- 5.3 Vuex References
- **5.1 Steps for using repositories in vue3**
- 5.2 modules (sub-modules)
- 5 .3 vuex-persistence
- Summary of the plugin persistence process:
- 5.5 Cannot use EventBus
- 5.4 Using the mitt library
- == Review: ==
- What's New in Vue3
- Distinction:
Vue3new feature
thrust
- Introduction to Vue3
- setup function
- Vue Component Data
- Calculation Properties and Listeners
- Communication between Vue components
Learning Objectives
point of knowledge (math.) | request |
---|---|
Introduction to Vue3 | grasp (often fig.) |
setup function | grasp (often fig.) |
Vue Component Data | grasp (often fig.) |
Calculation Properties and Listeners | grasp (often fig.) |
Communication between Vue components | grasp (often fig.) |
I. Introduction to Vue3
1.1 State of Vue3
- On September 18, 2020, the official release of vue3.0 version. But since it was just released the surrounding ecology does not support it, most developers are on the sidelines.
- Now the mainstream component libraries have been released to support vue3.0, and the rest of the ecosystem is constantly improving, this is the trend.
- element-plus desktop component library based on Vue 3.0
- vantvant3.0 version, have a praise front-end team open source mobile component library
- ant-design-vue (opens new window)Ant Design Vue version 2.0, community development based on ant ant design
Vue3 Pros:
- Hottest Framework, which is one of the hottest front-end frameworks in the country.Official Documentation (opens new window)Chinese document (opens new window)
- Improved performance, running at about 1.5 times the speed of the matter
- Smaller, on-demand compilation volume ratio to be smaller
- == type inference, better support for Ts (typescript) == this is also trending
- Advanced giving, exposing the underlying API and providing more advanced built-in components reactive runtime
- ★Composition API (composition api) , can better organize logic, encapsulate logic, reuse logic
Vue3 Outlook:
- This is the trend and more and more organizations will definitely upgrade to Vue 3.0 in the future!
- Large-scale projectsAs more and more large-scale projects become friendly to Ts, they can use Vue 3.0.
Summary: Why learn vue3 ?
- Adapt to the market to learn popular techniques to improve improve your competitiveness and give yourself a raise.
1.2 viteBasic use
What is vite:Official Documentation (opens new window)
- It is a much lighter (faster hot update, faster package build) scaffolding tool for vue projects.
- Compared to vue-cli it has very few plugins installed by default, and as the development process relies on more, you need to configure your own additional.
- So: We'll use it when we're just learning the vue3 syntax, and we'll use vue-cli when we're working on a project.
- What is vite? - A new generation of front-end build tools.
- The advantages are as follows:
- Development environment for fast cold starts without packaging operations.
- Lightweight and fast thermal reloading (HMR).
- True on-demand compilation, no more waiting for the entire application to compile.
vite basic use:
-
Create a project
npm init vite-app Project name
oryarn create vite-app Project Name
- Installation of dependencies
npm i
oryarn
- Installation of dependencies
-
Initiation of projects
npm run dev
oryarn dev
## Installation npm init vite@latest ## Create project npm init vite-app <project-name> ## Enter the project directory cd <project-name> ## Install dependencies npm install ## Run npm run dev
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Summary: What is vite?
- Use vite to create projects to learn vue3 syntax, use vue-cli to create projects for formal development
- Traditional build vs. vite build
vue-cli:
All in at once
Vite:
Load on Demand
1.3 Creating a vue project
- Install the latest version of the Vue-cli tool, which already provides Vue3-preview.
npm install -g @vue/cli
# OR
yarn global add @vue/cli
- 1
- 2
- 3
- Create Project Selection
[External link image dump failure, the source station may have anti-piracy chain mechanism, it is recommended to save the image directly uploaded (img-ikVSc2oU-1679832011514) (images\)]
[External link image dump failed, the source site may have anti-piracy chain mechanism, it is recommended to save the image and upload it directly (img-w2I6NnOl-1679832011515)(images\)]
Root Instance Initialization
In the middle, through thenew Vue()
method to initialize the
import Vue from 'vue'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Vue is no longer aconstructorThe app is initialized by the createApp method.
createApp(App).use(store).use(router).mount('#app')
- 1
install
1.4 Combined API
api: method Documentation
vue2 Options API Vue3 Combination API
- Code style: a functional logic of code organized together (contains data, functions ...)
- Advantages: complex functional logic in the case of a large number of functional logic code organization together, easy to read and maintain
- Cons: Requires good code organization and split logic skills, PS: No problem for everyone.
- Addendum: In order to make a better transition to vue 3.0, the
Option API writing is also supported
Better logic reuse and code organization
We've all fallen in love with Vue for its simplicity and ease of use, making it a breeze to build small to medium-sized applications. But as Vue's influence has grown, many users have begun to build larger projects with Vue. These projects are often teams of multiple developers, iterating and maintaining them over a long period of time. Over the years, we've witnessed some of these projects run into the limitations of the programming model imposed by Vue's current API. These issues can be categorized into two groups.
- As functionality grows, the code of complex components becomes increasingly difficult to read and understand. This is especially common when developers read code written by others. The root cause is that Vue's existing API forces us to organize code by options, but there are times when it makes more sense to organize code by logical relationships.
- There is a lack of a clean and low-cost mechanism for extracting and reusing logic between multiple components. The APIs proposed in the RFC provide more flexibility in the organization of component code. Instead of always organizing code by options, we can now organize code intoFunctions that handle specific functionsThese APIs also make it easier to extract and reuse logic between components and even outside of them. These APIs also make it easier to extract and reuse logic between components and even outside of them. We'll show the results in the Design Details section.
Better type derivation
Another common request from developers working on large projects is better TypeScript support; Vue's current API has had a lot of trouble integrating TypeScript, mainly because Vue relies on a simple this context to expose properties, and the way we're using this right now is a bit more subtle. (For example, the methods option underfunction (math.)(this points to the component instance, not the methods object). In other words, Vue's existing API was not designed with type derivation in mind, which complicates adapting to TypeScript.
Currently, most Vue developers using TypeScript are writing components as TypeScript classes (with the help of decorators) through the library vue-class-component. We designed 3.0 with a deprecated RFC to provide a built-in class API to better address typing issues. However, while discussing and iterating on the specific design, we noticed that trying to solve the type problem via the Class API required relying on the decorator - a very unstable stage 2 proposal with many unknowns in terms of implementation details. It would be extremely risky to rely on it. (For more information on type-related issues with the Class API, go here.)
In contrast, the proposal in this RFC makes greater use of common variables and functions that are naturally type-friendly. Code written using the APIs in this proposal will enjoy type derivation perfectly and will not need to do much additional type labeling.
This also equally means that you writeJavaScript The code is almost TypeScript code. Even non-TypeScript developers will benefit from better IDE type support!
II. The setup function
2.1 Introduction to the setup function
-
setup
is a new component option that is available as a component using theStarting point for portfolio APIs. Earliest implemented - In terms of the component lifecycle, it executes before the component instance is created
beforeCreate
Implementation. - This means that in
setup
in a functionthis
还不是组件实例,this
this timeundefined
- Data and functions that need to be used in the template need to be
setup
Return.
<template>
<div class="container">
<h1 @click="say()">{{msg}}</h1>
</div>
</template>
<script>
export default {
setup () {
('setupImplemented')
(this)
// Defining data and functions
const msg = 'hi vue3'
const say = () => {
(msg)
}
return { msg , say}
},
beforeCreate() {
('beforeCreateImplemented')
(this)
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
Summary: setup
Executed before the component is initialized, it returns data and functions that can be used in the template.
2.2 Combined API-Life Cycle
Recalling lifecycle hook functions: 11 keep-alive (Vue 2 is option API)
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
Getting to know vue3.0 lifecycle hook functions (7) Combinatorial APIs
The declaration cycle for vue3 has to be written in the setup, and the written declaration cycle is introduced on demand.
-
setup
Before creating an instance -
onBeforeMount
Before mounting the DOM -
onMounted
After mounting the DOM -
onBeforeUpdate
Before updating components -
onUpdated
After updating the component -
onBeforeUnmount
Before unloading and destruction -
onUnmounted
After unloading and destruction
Code Demo
<template>
<div class="container">
container
</div>
</template>
<script>
import { onBeforeMount, onMounted } from 'vue'
export default {
setup () {
onBeforeMount(()=>{
('DOMpre-render',('.container'))
})
onMounted(()=>{
('DOMafter rendering1',('.container'))
})
onMounted(()=>{
('DOMafter rendering2',('.container'))
})
},
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
[External link image dump failure, the source site may have anti-piracy chain mechanism, it is recommended to save the image directly uploaded (img-ff7SUco4-1679832011518)(images\)]
Attention:
There are seven lifecycle hooks for the Combined API, and you can use the same hook multiple times, in the same order of execution and writing.
Lifecycles can be written multiple times, and you can write two functions in two different lifecycles. To implement different logic
recount (e.g. results of election):
- Lifecycle needs to be written in setup
- Lifecycle functions need to be brought in on demand from vue
- Lifecycle function logic in callbacks
- It is possible to use the same lifecycle function multiple times, in the same order of execution and in the same order of writing
- Functions in setup do not end with a separate comma.
III. Vue component data
3.1 Introduction
ref or reactive replaces variables in data
In: Define some data for the current component via the component data method
data() {
return {
name: 'iwen',
list: [],
}
}
- 1
- 2
- 3
- 4
- 5
- 6
In: Creating responsive objects via ref or reactive
import { ref,reactive } from "vue"
export default {
name: 'HelloWorld',
setup(){
const name = ref("iwen")
const state = reactive({
list:[]
})
return{
name,
list
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
3.2 Combining API-ref Functions
Define responsive data:
- ref function.Commonly used to define simple data types as responsive data
- To modify the value again and get the value, you need ==.value==
- Responsive data in templates that use ref assertions can omit the .value
- For ref responsive data, you can log and see the specific code in it
- When modifying, use the defined property directly, without this pointing to the
- Modifying the .value of data only works for simple datatypes.
Code Demo
<template>
<div class="container">
<div>{{name}}</div>
<div>{{age}}</div>
<button @click="updateName"> Modify data</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'App', setup () {
setup () {
// 1. name data
const name = ref('ls')
(name)
const updateName = () => {
= 'zs'
}
// 2. age data
const age = ref(10)
// ref is often used to define responsive data for simple data types.
// It is also possible to define responsive data for complex data types.
// ref is best for cases where the data is not yet available.
// const data = ref(null)
// setTimeout(() =>{
},1000) // setTimeout(()=>{
// },1000)
return {name, age, updateName}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
templatesWhen parsing, it will determine if the data is created in the form of a ref and take out the value directly, so when using it in a template, omit the .value.
[external link image dump failure, the source station may have anti-piracy chain mechanism, it is recommended to save the image directly uploaded (img-VLG70WvO-1679832011520) (images/)image-)]
Usage Scenarios:
- Other cases use ref
- When you know exactly what is needed is a responsive databoyfriend Then just use reactive.
3.3 Combining API-reactive Functions
Define responsive data:
- reactive is a function that defines a complex data type that becomes responsive. {} []
- Typically used to define responsiveobject data
Demo code:
<template>
<div>
<p>{{}}</p>
<p><button @click="updateName">Modify name</button></p>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup () {
// General data
// const obj={
// name:'zs',
// age:18
// }
const obj=reactive({
name:'zs,I'm responsive.',
age:18
})
const updateName=()=>{
('updateName....');
='lisi'
}
return {obj,updateName}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
3.4 The toRef function
toRef is a function that convertsresponsive objectcentersomeattribute is individually responsive data, and == theIt is associated with the value of the original data.==。
As in the above example, you only want to access the name attribute in the responsive object obj without name.
Data that is deconstructed through an object is not responsive. You need to use the toRef
<template>
<div>
<p>{{ name }}</p>
<p> <button @click="updateName"> modify</button> </p>
</div>
</template>
<script>
import { reactive, toRef } from "@vue/reactivity";
export default {
setup() {
// Define the responsive data
const obj = reactive({
name: "zs",
name: "zs", age: 18, }); }
});
// Only use name, in the module
// Note: the data deconstructed from responsive is no longer responsive!!!!
// let {name}=obj;
let name = toRef(obj, "name");
const updateName = () => {
("updateName、、、、");
// toRef converts the responsive data wrapped into an object, where value holds the values
= "I'm lisi after the modification Ah";
};
return { name, updateName }
}, }
}; }
}, }; </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
Usage scenario: there is a responsive object data, but only one of the data needs to be used in the template.
3.5 The toRefs function
-
toRefs are functions that convertresponsive objectcenterAll PropertiesFor individually responsive data, the object becomes a normal object and == theValues are associated==
<template> <div> <p>{{ name }}</p> <p>{{ age }}</p> <p> <button @click="updateName"> modify</button> </p> </div> </template> <script> import { reactive, toRef, toRefs } from "@vue/reactivity"; export default { setup() { // Define the responsive data const obj = reactive({ name: "zs", name: "zs", age: 18, }); } }); const obj2={... const obj2 = {. .obj}; (obj2); const obj3=toRefs(obj) const obj3=toRefs(obj) (obj3). const updateName = () => { ("updateName、、、、"); = 'changed oh,,,' // Can also change the original data, since [the values are linked] // = 'can also change the original data' }; return { ... .obj3, updateName }; } }, } }; return { ...obj3, updateName }; }, } }, }; </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
[External link image dump failure, the source station may have anti-piracy chain mechanism, it is recommended to save the image directly uploaded (img-gTAh2dA9-1679832011521)(images/)]
Usage Scenario: Stripped responsive object (deconstructed|expanded), want to use multiple or all attributes in the responsive object as responsive data.
Understandably, users will struggle with whether to use ref or reactive, and the first thing you need to know is that you need to know both to be able to use the combinatorial API efficiently, and that using only one of them is likely to needlessly complicate your work, or create wheels over and over again. The difference between using ref and reactive can be compared by how you write standard JavaScript logic
// Style 1: Separating Variables
let x = 0
let y = 0
function updatePosition(e) {
x = e.pageX
y = e.pageY
}
// --- compared to the following ---
// Style 2: Single Object
const pos = {
x: 0,
y: 0,
}
function updatePosition(e) {
pos.x = e.pageX
pos.y = e.pageY
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- If we use ref, we are actually converting style (1) to a more nuanced way of writing using ref (in order to make the base type value responsive).
- Using reactive is consistent with style (2). We just need to create the object via reactive.
To summarize, there are two variable styles:
- We recommend that you use the type system in this style in conjunction with the IDE, just as you would distinguish between ref and reactive when declaring a basic type variable and an object variable in normal JavaScript.
- Use reactive in all places, and then remember to use toRefs when the composite function returns a responsive object.This reduces some of the mental burden of ref, but it doesn't mean that you don't need to familiarize yourself with the concept.
At this stage, we think it's too early to force a decision on best practices for ref vs. reactive. We recommend that you experiment with both of these approaches and choose a style that works better with your mental model. We will continue to gather feedback from users in the surrounding ecosystem and ultimately provide clearer and more consistent practice guidance on this issue!
3.6 Cases of knowledge utilization
take note of: For the use of data, you must return it to be used in the html interface.
Basic Steps:
- Record mouse coordinates
- Define a responsive data object containing x and y attributes. ===> responsive data object { x: y:}
- Listen for mouseover events on document after the component has been rendered ==> event binding, DOM, onMounted unbinding: onUnmounted
- Specify the move function as the corresponding method for the event, and modify the coordinates in the function ==> modify the data of the responsive object
- Return data in setup, used in templates
- Accumulate 1 function
- Define a simple data type for responsive data
- Define a method to modify a number
- In setup return data and functions, the template uses the
Drop the code:
<template>
<div class="container">
<div> coordinates</div>
<div> x: {{x}}</div>
<div>y: {{y}}</div>
<hr>
<div>{{count}} <button @click="add">Accumulate 1</button></div>
</div>
</template>
<script>
import { onMounted, onUnmounted, reactive , ref, toRefs} from 'vue'
const useMouse = () => {
// 1. Record the mouse coordinates
// 1.1 Declare a reactive data, which is an object containing x y
const mouse = reactive({
x: 0,
y: 0
})
// 1.3 Modifying responsive data
const move = (e) => {
=
= =
}
// 1.2 Wait for the dom to render. Go listen to the event
onMounted(()=>{
('mousemove', move)
})
// 1.4 Component destruction, delete event
onUnmounted(()=>{
('mousemove', move)
})
return mouse
}
export default {
name: 'App', setup () {
setup () {
const mouse = useMouse()
// 2. adding numbers
const count = ref(0)
const add = () => {
++ // Always remember .value.
}
// Simply . .mouse will not work, you need toRefs, and then deconstruction
return { ... .toRefs(mouse), count, add }
}
}
</script>.
<style scoped lang="less"> </style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
Encapsulation:
const useMouse = () => {
// Declare responsive data
const mouse = reactive({
x: 0,
y: 0,
});
// 修改响应式数据
const move = (e) => {
// ();
// ();
mouse.x = e.pageX;
mouse.y = e.pageY;
};
// 等dom渲染完毕。去监听事件
onMounted(() => {
document.addEventListener("mousemove", move);
});
// 组件卸载,删除事件
onUnmounted(() => {
document.removeEventListener("mousemove", move);
});
// 一定要return 出去!!!!
return mouse;
};
export default {
setup() {
const mouse = useMouse();
// Defining Responsive Data
let count = ref(0);
const add = () => {
count.value++; //must remember the .value
};
// return { mouse };
// Simply . .mouse deconstruction won't work, you need toRefs, and then deconstruction.
return { ...toRefs(mouse), count, add };
},
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
3.7 Supplementary: the ref attribute:
Vue2 :
ref attribute: 1) Get DOM element 2) Get subcomponent instance
Vue3: ref attribute can still get DOM elements and get component instances
IV. Computational properties and listeners
4.1 Calculation of properties
In : Calculated properties
computed: {
storeData () {
return this.$store.state.storeData
},
}
- 1
- 2
- 3
- 4
- 5
favorable conditions
import {computed} from 'vue'
setup(){
//Functional form
const storeData = computed(() => store.state.storeData)
return {
storeData
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Compute attribute bidirectional bindings:
let newMoney=computed({
//Object Form
get(){
return money.value * 6;
},
set(val){
money.value=val/6
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Summary:
Two ways to write the calculation property:
- Pass a function to the computed property, and the return value is the value of the computed property.
- Pass an object to the computed attribute, ge() returns the value of the computed attribute; set(val) is the value set for the computed attribute
4.2 The watch listener
At the time of versioning the code was as follows
export default {
data() {
return {
counter: 0
}
},
watch: {
counter(newValue, oldValue) {
console.log('The new counter value is: ' + this.counter)
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
At the time of versioning the code was as follows
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log('The new counter value is: ' + counter.value)
})
- 1
- 2
- 3
- 4
- 5
- 6
watch function
The watch function, which is used to define the listener's
-
Listening for responsive data defined by ref
-
Listen to multiple responsive data data: listen to multiple data, watch([data1, data2], ( )=>{ }) Just write the data you want to listen to in object mode
-
Listening for responsive data defined by reactive
-
Listening to responsive data defined by reactive, an attribute
-
It is possible to implement a property in a listening object
watch( ()=> obj.name,(newname,oldname) =>{ log - newname log- oldname })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Deep Listening Other objects in the object
default execution
<template>
<div class="container">
<div>
<p> value of count: {{count}}</p>
<button @click="add"> change data</button>
</div>
<hr>
<div>.
<p>{{}}</p>
<p>{{}}</p>
<p>{{}}</p>
<button @click="updateName">change ones name</button>
<button @click="updateBrandName">Change of brand name</button>
</div>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
name: 'App',
setup () {
const count = ref(0)
const add = () => {
++
}
// When you need to listen for changes in data you can use thewatch
// 1. listens to arefdigital
// watch(count, (newVal,oldVal)=>{
// (newVal,oldVal)
// })
const obj = reactive({
name: 'ls',
age: 10,
brand: {
id: 1,
name: 'BMW (car company)'
}
})
const updateName = () => {
= 'zs'
}
const updateBrandName = () => {
= 'run quickly'
}
// 2. listens to areactivedigital,object name,direct arrow function
watch(obj, ()=>{
('digital改变了')
})
watch(()=>, ()=>{
('branddigital改变了')
},{
//deep listening
deep: true,
//Immediate implementation
immediate: true
})
return {count, add, obj, updateName, updateBrandName}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
V. Communication between Vue components
5.1 Combined API - Parent-Child Communication
The data acceptance of the parent to the child is props, using the data in props, utilizing the parameters in setup
Custom events, vue3 can not get this, the use of content, his emit can be
Simpler object structure
Father to son:
<template>
<div class="container">
<h1> parent component</h1>
<p>{{money}}</p>
<hr>
<Son :money="money" />
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './'
export default {
name: 'App',
components: {
Son
},
// Parent component's data passed to child component
setup () {
const money = ref(100)
return { money }
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
<template>
<div class="container">
<h1> subcomponent</h1>
<p>{{money}}</p>
</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
name: 'Son',
// The child component receives data from the parent component using thepropscan immediately (do sth)
props: {
money: {
type: Number,
default: 0
}
},
setup (props) {
// Get parent component datamoney
()
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
lit. the son passes on to the father
Subcomponent: setup (props, {emit})
context can provide the emit method, which notifies the parent component that it is directly decontextualized
<template>
<div class="container">
<h1> subcomponent</h1>
<p>{{money}}</p>
+ <button @click="changeMoney"> Spend $50</button>
</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
name: 'Son', // Child component receives data from parent component.
// The child component receives the parent component's data using props.
props: {
money: {
type: Number, default: 0
default: 0
}
}, }
// props parent component data
// emit function that triggers a custom event
+ setup (props, {emit}) {
// Get the parent component data money
()
// Pass the value to the parent component
+ const changeMoney = () => {
+ emit('change-money', 50)
+ }
+ return {changeMoney}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
The parent component listens:
<template>
<div class="container">
<h1> parent component</h1>
<p>{{money}}</p>
<hr>
+ <Son :money="money" @change-money="updateMoney" />
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './'
export default {
name: 'App',
components: {
Son
},
// Parent component's data passed to child component
setup () {
const money = ref(100)
+ const updateMoney = (newMoney) => {
+ = newMoney
+ }
+ return { money , updateMoney}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
Parameters of setup
-
setup(props, context) / setup(props, {attrs, slots, emit})
-
props: An object containing all the properties declared by the props configuration and passed in.
Get the data passed from the parent component to the child component
-
attrs: object containing attributes not declared in the props configuration, equivalent to this.$attrs
Get the data passed from the parent component to the child componentand have not been received via props.
(accepts all data passed from the parent to the child, provided that the city does not declare it in the porps again)
-
slots: object containing the contents of all incoming slots, equivalent to this.$slots
-
emit: A function used to emit custom events passed from parent to child, equivalent to this.$emit
Parent component:
<template>
<h2>App</h2>
<p>msg: {{msg}}</p>
<button @click="fn('--')">update</button>
<child :msg="msg" msg2="cba" @fn="fn"/>
</template>
<script>
import {
reactive,
ref,
} from 'vue'
import child from './'
export default {
components: {
child
},
setup () {
const msg = ref('abc')
function fn (content) {
+= content
}
return {
msg, fn
}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
Subcomponents:
<template>
<div>
<h3>{{n}}</h3>
<h3>{{m}}</h3>
<h3>msg: {{msg}}</h3>
<h3>msg2: {{$attrs.msg2}}</h3>
<slot name="xxx"></slot>
<button @click="update">update</button>
</div>
</template>
<script lang="ts">
import {
ref,
defineComponent
} from 'vue'
export default defineComponent({
name: 'child',
props: ['msg'],
emits: ['fn'], // optional, Declared to be more programmer-friendly, And you can validate the distributed event data.
data () {
('data', this)
return {
// n: 1
}
},
beforeCreate () {
('beforeCreate', this)
},
methods: {
// update () {
// ++
// ++
// }
},
// setup (props, context) {
setup (props, {attrs, emit, slots}) {
// Component not created,this at a loss,So it's a good idea to pass props
('setup', this)
(, attrs.msg2, slots, emit)
const m = ref(2)
const n = ref(3)
function update () {
// ('--', this)
// += 2
// += 2
+= 2
+= 2
// Distribute custom events
emit('fn', '++')
}
return {
m,
n,
update,
}
},
})
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
5.2 Provide / Inject
Applicable Scenarios:deep transfer
It's worth mentioning the Provide / Inject applications, which have been enhanced in the
- provide() and inject() enable data passing between nested components.
- These two functions can only be used in the setup() function.
- Use the provide() function in the parent component to pass data down the chain.
- Use inject() in the child component to get the data passed from the upper level.
- Unlimited Hierarchy Parent component:
<template>
<div>
<provideAndInject />
</div>
</template>
<script>
import { provide } from "@vue/composition-api"; // Parent component introduction provide
import provideAndInject from "./components/provideAndInject"; // Introducing subcomponents
export default {
name: "app",
components: {
provideAndInject
},
setup() {
// provide('data name', data to be transmitted)
provide("customVal", "I'm the value passed from parent component to child component");
}
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
subassembly
<template>
<div>
<h3>{{ customVal }}</h3>
</div>
</template>
<script>
// Subcomponent import inject
import { inject } from "@vue/composition-api";
export default {
setup() {
// Call the inject function to get the parent's shared data with the specified data name
const customVal = inject("customVal");
return {
customVal
}; return { customVal
}
}; }
}; }; </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
Provide data to descendants and also methods
<template>
<div class="container">
<h1> parent component {{money}} <button @click="money=1000">pay</button></h1>
<hr>
<Son />
</div>
</template>
<script>
import { provide, ref } from 'vue'
import Son from './'
export default {
name: 'App',
components: {
Son
},
setup () {
const money = ref(100)
// 谁定义,谁修改原则
const changeMoney = (saleMoney) => {
('changeMoney',saleMoney)
= - saleMoney
}
// 将数据提供给后代组件 provide
provide('money', money)
// Making functions available to descendant components provide
provide('changeMoney', changeMoney)
return { money }
}
}
</script>
<style scoped lang="less"></style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
Subcomponents:
<template>
<div class="container">
<h2> subcomponent {{money}}</h2>
<hr>
<GrandSon />
</div>
</template>
<script>
import { inject } from 'vue'
import GrandSon from './'
export default {
name: 'Son',
components: {
GrandSon
},
setup () {
// Receive data from ancestor components
const money = inject('money')
return { money }
}
}
</script>
<style scoped lang="less"></style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
Sun Assembly
<template>
<div class="container">
<h2> subcomponent {{money}}</h2>
<hr>
<GrandSon />
</div>
</template>
<script>
import { inject } from 'vue'
import GrandSon from './'
export default {
name: 'Son',
components: {
GrandSon
},
setup () {
// Receive data from ancestor components
const money = inject('money')
return { money }
}
}
</script>
<style scoped lang="less"></style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
Summary:
- The provide function provides data and functions for use by descendant components.
- The inject function injects the data and functions provided by the provider into the current component.
- Data communication: follow the principle of unidirectional data flow, who defines, who modifies
- Steps in the transmission methodology
- 祖先组价定义好方法,provide传递,后代组件inject接受组件,定义为一个新的方法,
- 后代组件写一个Click或者其他事件,再次调用祖先组件传递过来的方法
5.3 Vuex引用
安装:npm install vuex@next --save
在版本对store对象的引用是通过this对象
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在版本对store引用变为createStore方法
5.1vue3中使用仓库步骤
- Define Warehouse
import { createStore } from 'vuex'
export default createStore({
// Define the data
state: {
name: 'HHX'
},
// Define the method
mutations: {
UpdateName(state, payload) {
state.name = payload
}
},
// Asynchronous processing
actions: {
// context contains various
UpdateNameAsync({ commit }, payload) {
setTimeout(() => {
commit('UpdateName', payload)
}, 2000);
}
},
//Packaging of data
getters: {
newName(state) {
return state.name + 'Hello!'
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
-
Importing the repository and registering it
import { createApp } from 'vue' import App from './' import './' // Import the store after it's been created import store from '../src/store/index' // Installation after importing srore createApp(App).use(store).mount('#app')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
-
Referencing the store object in a component
<template>
<div>
<h1>Home</h1>
<p>Referencing data in the store--{{ $store.state.name }}</p>
<p>Referencing data in the store---{{ $store.getters.newName }}</p>
<button @click="ChangeName"> Trigger mutations to change name</button>
<button @click="ChangeNameAsync"> Trigger action to change name</button>
</div>
</template>
<script>
// Introducing data from the store
import { useStore } from 'vuex'
export default {
setup(props) {
// The usestore is called, which is equivalent to this in vue2.
const store = useStore()
console.log(store.state.name);
const ChangeName = () => {
// Triggering mutations uses commit.
store.commit('UpdateName', 'PDD')
}
const ChangeNameAsync = () => {
// Triggering mutations uses commit.
store.dispatch('UpdateNameAsync', 'BBT')
}
return { ChangeName ,ChangeNameAsync }
}
}
</script>
<style lang="less" scoped></style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
It is worth noting that most of the time we use vuex will refer to the extension operator, if you use the extension operator according to the current official website vuex documentationVersion (opens new window)which still needs to be handled in methods
5.2 modules (sub-modules)
Two scenarios exist
The default module.state
Distinguishing modules, othergetters
mutations
actions
All across the board.
namespacenamespaced: true
of modules, all functions distinguish modules for higher encapsulation and reuse.
After defining the module import, you must also register the module in the repository store's module
import { createStore } from 'vuex'
const moduleA = {
// The submodule state is recommended to be written as a function
state: () => {
return {
username: 'Module A'
}
},
getters: {
changeName (state) {
return state.username + 'AAAAAA'
}
}
}
const moduleB = {
// Modules with namespaces
namespaced: true,
// The submodule state is recommended to be written as a function
state: () => {
return {
username: 'Module B'
}
},
getters: {
changeName (state) {
return state.username + 'BBBBBB'
}
},
mutations: {
// Modify the name mutation
update (state) {
state.username = 'BBBB' + state.username
}
},
actions: {
update ({ commit }) {
// Hypothetical request
setTimeout(() => {
commit('update')
}, 2000)
}
}
}
// Create vuex repository and export
export default createStore({
state: {
// Data
person: [
{ id: 1, name: 'tom', gender: 'Male' },
{ id: 2, name: 'lucy', gender: 'Female' },
{ id: 3, name: 'jack', gender: 'Male' }
]
},
mutations: {
// Change data function
},
actions: {
// Request data function
},
modules: {
// Sub-modules
a: moduleA,
b: moduleB
},
getters: {
// vuex's computed properties
boys: (state) => {
return state.person.filter(p => p.gender === 'Male')
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
Use:
<template>
<div> APP component</div>
<ul>
<li v-for="item in $" :key=""> {{}}</li>
</ul>
<! -- Use module A's username -->
<p> A's username --- {{$}}</p>
<p>A's changeName --- {{$}}</p>
<hr>
<p> B's username --- {{$}}</p>
<p>B's changeName --- {{$['b/changeName']}}</p>
<button @click="$('b/update')">modificationsusername</button>
<button @click="$('b/update')">异步modificationsusername</button>
</template>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
5 .3 vuex-persistence
Vue2 uses local storage.
During development, things like user information (name, avatar, token) need to be stored in vuex and need to be stored locally.
Another example is the shopping cart if it needs to be supported even when not logged in, and if the management is in vuex the page needs to be stored locally.
We need the category module to store the category information, but the categories don't need to be persistent.
1) First things first: we need to install a vuex pluginvuex-persistedstate
to support vuex state persistence.
npm i vuex-persistedstate
- 1
2) Then: insrc/store
Create a new foldermodules
file in themodules
newbuilding respond in singing
src/store/modules/
// User Module
export default {
namespaced: true,
state () {
return {
// User information
profile: {
id: '',
avatar: '',
nickname: '',
account: '',
mobile: '',
token: ''
}
}
},
mutations: {
// Modify the user information, the payload is the user information object.
setUser (state, payload) {
state.profile = payload
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
src/store/modules/
// Shopping cart status
export default {
namespaced: true,
state: () => {
return {
list: []
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
src/store/modules/
// Classification Module
export default {
namespaced: true,
state () {
return {
// Classifieds collection
list: []
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
3) Continued: insrc/store/
import the user cart module.
- After defining the module certain registration
import { createStore } from 'vuex'
import user from './modules/user'
import cart from './modules/cart'
import cart from './modules/category'
export default createStore({
modules: {
user,
cart,
category
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
4) Finally: persistence using the vuex-persistedstate plugin
import { createStore } from 'vuex'
//Persistence
import createPersistedstate from 'vuex-persistedstate'
import user from './modules/user'
import cart from './modules/cart'
import category from './modules/category'
export default createStore({
modules: {
user,
cart,
category
},
+ plugins: [
+ createPersistedstate({
+ key: 'pc-store', //Local storage when the previous key
+ paths: ['user', 'cart'] //Persistence on specific modules
+ })
+ ]
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
Attention:
===> By default, it is stored in localStorage.
===> key is the name of the key that stores the data.
===> paths is to store those data in the state, if it is specific data under the module need to add the module name, such as
===> Triggered by modifying the state to see the changes in the locally stored data.
Testing: The user module defines a mutation in the go-to call to observe the data under the browser application's localStorage.
src/
<template>
<div class="container">
<! -- Modify data to test for persistence -->
App {{$}}
<button @click="$('user/setUser',{account:'zhoujielun'})">Setting up user information</button>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Summary of the plugin persistence process:
-
mounting
npm i vuex-persistedstate -s
- 1
-
pull into
import createPersistedstate from 'vuex-persistedstate'
- 1
-
Registration Plugin
export default createStore({
plugins:[
Ceratepersistedstate({
key:'info',
paths:['moduleA']
})
],
// 定义数据
state: {
name: 'HHX'
},
......
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Code organization skills
In versioning, too much DATA and METHODS code will not be easy to maintain, too many attributes and too many methods cause a lot of trouble for developers both in reading and maintaining. In versioning, we can organize the code better, examples are as follows:
We separate a data processing file
import { ref,reactive } from "vue"
export function article(){
const currentArt = ref("Test data");
const artLists = reactive({
name:"Title.",
content:"Content"
})
function changeArt(){
currentArt.value = "New test data"
}
return{
currentArt,
artLists,
changeArt
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
We can separate a web request file processing
import { ref,reactive } from "vue"
import axios from "axios"
export function getBanner(){
const netState = reactive({
banner:{}
})
function http(url){
axios.get(url).then(res =>{
netState.banner = res.data
})
}
return {
netState,
http
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
We can introduce it in the main business file as follows.
import { article } from "./HelloWorld";
import { getBanner } from "./NetWork";
export default {
setup(props, ctx) {
const { netState, http } = getBanner();
onMounted(() => {
http("/api/blueberrypai/")
});
const { currentArt, artLists, changeArt } = article();
return {
currentArt,
artLists,
changeArt,
netState
};
},
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Status Management
Vuex is a great state management library that is easy to understand and integrates well with Vue. Why not just use Vuex? Because the upcoming release of Vue3 exposes the underlying responsive system and introduces new ways to build applications. The new responsive system is powerful and can be used for shared state management.
Do you need a shared state?
In some cases, data sharing between multiple components is so difficult that centralized state management is required. Situations include:
- Multiple components using the same data
- Multiple root modules require separate access to data
- Deeply nested components need to communicate data with other components
If none of the above situations exist, then it's an easy decision to make: you don't need it. What if the above situation exists? The most straightforward answer is to use Vuex, which is a battle-tested solution that works well. Don't want to add another dependency or don't want to do too much configuration? Then it's now possible to solve these problems with the new Vue3 built-in methods along with the Composition API.
New solutions
The shared state must meet two criteria:
- Responsive: when the state changes, the components that use them update accordingly
- Availability: can be accessed in any component
responsive
Vue3 exposes numerous functions of its responsive system to the public, and you can use thereactive
function creates areactive
variable (you can also use theref
function)
import { reactive } from 'vue';
export const state = reactive({ counter: 0 });
- 1
- 2
- 3
The object returned from the responsive function is aProxy
object that listens for changes to its properties. When used in a component template, the component is re-rendered whenever the response value changes:
<template>
<div>{{ }}</div>
<button type="button" @click="++">Increment</button>
</template>
<script>
import { reactive } from 'vue';
export default {
setup() {
const state = reactive({ counter: 0 });
return { state };
}
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
usability
The above example is perfect for a single component, but not for multiple components sharing state. To overcome this, you can use Vue3'sprovide
together withinject
:
import { reactive, provide, inject } from 'vue';
export const stateSymbol = Symbol('state');
export const createState = reactive({ counter: 0 });
export const setCounter = (num) =>{
createState.counter = num
}
export const useState = () => inject(stateSymbol);
export const provideState = () => provide(
stateSymbol,
createState
);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
When you willSymbol
Passed as a key value to theprovide
When the value will be passed through theinject
method makes any component available. Keys are provided and retrieved using the sameSymbol
Name.
As shown above, if you provide the value on the topmost component, it will be available in all components, or you can call provide on the main file of the application
import { createApp } from 'vue';
import App from './';
import { stateSymbol, createState } from './store';
createApp(App).provide(stateSymbol, createState).mount('#app');
<template>
<div class="about">
<h1>This is an about page</h1>
<p>{{ state.counter }}</p>
<button @click="changeCounter">modifications</button>
</div>
</template>
<script>
import { useState,setCounter } from "../store"
export default{
setup(){
function changeCounter(){
setCounter(100)
}
return{
state:useState(),
changeCounter
}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
By using Vue3's responsive system and dependency injection mechanism, we have changed from local state management to global state management and this solution can replace Vuex in small applications. But this solution is not suitable for large projects or if there are features that use Vuex, e.g., you don't know who made the state changes because the state can be changed directly without any restrictions. So based on this, large projects still need to use Vuex.
5.5 Cannot use EventBus
EventBus global event bus, a way to pass data, no limitations between parent and child
this.$emit() v-on
this.$on
Any component:
- e m i t ( ) 、 . emit()、. emit()、.on =》 {}
- Any component can this vm ===
Component communication is achieved through EventBus methods in the
var EventBus = new Vue()
Vue.prototype.$EventBus = EventBus
...
this.$EventBus.$on() this.$EventBus.$emit()
new Vue({
cretead(){
Vue.prototype.$EventBus =this;
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
The methods $on, $off, etc. have been removed (cf. rfc), and the mitt scheme is recommended instead.
import mitt from 'mitt'
const emitter = mitt()
// fire an event
emitter.emit('foo', { a: 'b' })
// listen to an event
emitter.on('foo', e => console.log('foo', e) )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Installation:
npm i mitt -S
- 1
5.4 Using the mitt library
-
is also a way to pass values, Vue2 mounts the prototype object directly, Vue3 uses a mitt library, the
-
emit Send data on Accept data
-
keep in mind 全局事件总线的emit 需要触发 才可以
-
可以在单独的文件暴露出事件总线对象
utils/:
// mitt库默认导出的是一个函数,我们需要执行它从而得到事件总线的对象 /* */ // 这里我们在js中暴露这个事件总线对象 import mitt from "mitt"; const emitter = mitt(); export default emitter;
- 1
- 2
- 3
- 4
- 5
- 6
-
-
在指定组件中导入并使用它!
// 导入事件总线 import emitter from "../../util/eventbus"; //全局事件总线需要一个触发条件 const toSon2 = () => { // 触发自定义总线why,并传入一个对象 emitter.emit("toSon2", { name: "张三", age: 19 } }; return { toSon2 };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-
// 导入事件总线 import emitter from "../../util/eventbus"; // 在创建vue实例时,注册why事件总线 ,Vue3 支持Vue2的写法 created(){ emitter.on("why",msg=>{ console.log("HomeContent接收到得About发送得数据了:",msg); } setup(props) { emitter.on("toSon2", (msg) => { console.log("HomeContent接收到得About发送得数据了:", msg); }); // 的第一个参数如果是 * 代表监听所有的事件触发! // 这时,回调函数的参数就会有2个,1是事件的类型,2是实际实参 emitter.on("*", (eventType, item) => { console.log(`* 监听到的事件类型是:${eventType},接收的参数为:`, item); }); },
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
回顾:
What's New in Vue3
-
Fast, efficient and compact
-
Typescript is introduced to allow for type inference
-
Introducing the Combination API for better logic reuse, encapsulated logic Vue2: Options API
new Vue({ router、 vuex })
- 1
- 2
- 3
- 4
-
Vue3 has full support for Vue2 and is easy to upgrade.
Distinction:
-
Creating a component instance =>Vue3 Hook
import {createApp} from 'vue' new Vue({ router、 vuex }) createApp()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
setup: the starting point of the Portfolio API, predating Vue2 beforeCreate.No this , undefined No access to data, methods, this.
setup(){ let msg='123' return {msg,,,,,,} }
- 1
- 2
- 3
- 4
- 5
-
Life Cycle:
Vue2 (11) Vue components from creation to destruction. : 8
beforeCreated, created (earliest to send a network request, THIS),
beforeMount, Mounted (mount complete , DOM, bind events, turn on timer),
beforeUpdate (after the data is updated, before the interface update is updated), updated,
beforeDestory (before destruction, wrapping up, clearing timers, unbinding events, registering forms: can be a friendly reminder), Destoryed
Vue3:
setup OnMounted OnUnmounted
Lifecycles are written in setup.
import {onMounted} from 'vue' data(){ }, methods:{ }, mounted(){ } setup(){ onMounted(()=>{ // Logic //Send web request }) reutrn {} }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
-
Define responsive data:
Vue2: data, props, computed, watch are all responsive
ref : define the basic data type as responsive
To modify a value, use the .value
let num=ref(10) // (num) changeNUm=()=>{ num.value=11; }
- 1
- 2
- 3
- 4
- 5
reactive:Define complex data types as responsive {} []
const obj=reactive({})
- 1
When unsure of the data type:
const res= ref(null)
- 1
- 2
- 3
-
data conversion
toRef: responsive object data becomes a property becomes responsive
let name = toRef(obj, "name");
- 1
- 2
- 3
toRefs: responsive data object becomes responsive with all properties
const obj3= toRefs(obj) setup(){ reutrn {...toRefs(obj)} }
- 1
- 2
- 3
- 4
- 5
- 6