Vue
Personal website is constantly updated
Changes to Vue2.0 and Vue3.0
DefineProperty in Vue2.0 and Proxy in Vue3.0
let obj = { name: []};// proxy
obj = new Proxy(obj, {
get(target, prop) {
return target[prop]
},
set(target, prop, val) {
target[prop] = val
}
})
// Object.defineProperty
let newObj = JSON.parse(JSON.stringify(obj))
Object.defineProperty(obj, 'name', {
get() {
return newObj.name
},
set(val){ newObj.name ! == val && (obj.name = val) } })Copy the code
In Object. DefineProperty, you need to recursively listen for each attribute, which not only wastes performance, but also can’t listen if there is no attribute defined in the initial value. This means that new attributes in Vue2.0 will not change in view. Hence the need to use $set for new attributes
Vue2.0
Why does the virtual DOM perform better
Virtual DOM is equivalent to using JS to construct the page into a DOM tree with object structure. When changes occur, the old DOM tree will be compared with the new DOM tree to find out the differences, and finally render the real DOM
Why is data a function
If two instances refer to the same object, when the properties of one instance change, the properties of the other instance also change. Only when the two instances have their own scope can they not interfere with each other, that is, there is no variable pollution
Why does Vue use asynchronous rendering
The fundamental reason is to improve performance. To put it simply, when data changes, the data is not immediately updated, but temporarily stored in asynchronous functions. After the synchronization operation is completed, the asynchronous operation is performed to process the data, and finally the valid data is updated to the view.
The principle of two-way data binding, how to customize v-Model
Vue2.0: Data hijacking combined with the publiser-subscriber pattern, using Object.defineProperty() to hijack the setter and getter of each attribute, publish the message to the subscriber when the data changes, and trigger the corresponding listener callback
Implement two-way data binding
-
Custom v – model
<! -- Parent component register and use --> <k-input v-model="search" placeholder="Please enter your search terms"></k-input> <! -- Subcomponent --> <input type="text" :value="value" @input="handleInput" /> Copy the code
/ / child component export default { name: "kInput".model: { prop: "value".event: "input",},props: ["value"].methods: { handleInput(e) { this.$emit("input", e.target.value); ,}}};Copy the code
The principle of event binding
The difference between watch and computed
- Watch: The listening attribute depends on the cache and is recalculated only when the dependency changes. Recommended for listening on multiple data at the same time
- Immediate: Executes immediately
- “Deep” : deep listening
- Computed: Computed attribute data changes are triggered immediately
Component communication
-
Parent-child component communication
- Parent —–> child: props passes the value, the child props receives the value, and the ref can be used to obtain the data and methods of the child component
- Child —–> parent: $emit() calls the method passed by the parent component and carries arguments to the parent component
-
Non-parent component communication
-
Bus Event bus
-
provide / inject
// Ancestor component provide: {provideData:"hello" } // Descendant components / / 1. inject: ["provideData"] / / 2. inject: {provideData: {from:"provideData".default:"hello"}}Copy the code
-
Vuex
-
Route Configuration
import Vue from "vue";
import vueRouter from "vue-router";
Vue.use(vueRouter);
// Nested by
routes: [{
path: '/offerreward'.name: 'offerreward'.component: () = > import('path'),
children: [{
path: 'rewIndex'.name: 'rewardIndex'.component: () = > import('path'),}}]]// Route redirection
{ path: 'Current route'.redirect: 'Redirect destination route'}
// For vue-Router 4.0, it matches an unfound route notation
{ path: '/:pathMatch(.*)*'.redirect: "/ 404" }
// Dynamic routing
{ path: 'Current route /:id'.component: () = > import('path')}
// The address bar can match the current route with the current route /123. The page can obtain the ID through params
// Route parameters are transmitted
// The page can be passed query or params to receive arguments through this.$route
Copy the code
Route guard and execution order
- Routing guard
beforeEach
: Global front guardbeforeResolve
: Global parsing guardbeforeEnter
: Route exclusive guardafterEach
: Global rear guardbeforeRouteEnter
: component internal guard, called until the corresponding route to render the component has been confirmed, cannot access this, can pass a callback to Next to get the component instance (also the only hook that can pass a callback to Next)beforeRouteUpdate
: internal component guard, called when the current route has changed but the component is being reusedbeforeRouteLeave
: Guard inside a component, called when navigating away from the corresponding route of the component
- Execution order
- Navigation is triggered.
- Called in a deactivated component
beforeRouteLeave
The guards - Call global
beforeEach
The guards - Called in a reused component
beforeRouteUpdate
The guards - Called in the routing configuration
beforeEnter
- Parse the asynchronous routing component
- Called in the active component
beforeRouteEnter
- Call global
beforeResolve
The guards - Navigation confirmed
- Call global
afterEach
Hook. - Trigger a DOM update.
- Call with the created instance
beforeRouteEnter
Guard passnext
The callback function of
Programmatic and declarative navigation
- Programmatic navigation:
router.replace(...)
- Declarative navigation:
<router-link :to="..." replace>
- How to pass parameters:
to="{path:'/test',query:{name:id}}
- How to pass parameters:
- The difference between Push and replace:
- Push adds a new record to history
How do I manage rights
-
Menu management
- Front-end management: Set meta labels in the route, set role array, save the user’s permission during login for judgment, and hide or display the menu bar
- Combination of the front and back ends: Sometimes the menu is returned to the back end, and the administrator has the ability to modify permissions
- Of course, in both ways, the route guard needs to determine whether the current route to be entered has the corresponding permission. If not, the route is redirected to the corresponding route
-
Operation management (front-end only, not back-end)
- Determine the route permission based on the route configuration
What are the routing modes? What are the differences? How do they work?
- Hash: the character after #. Changing the hash will not rehash the HTTP request
- History: Refreshing the page if there is no back-end configuration, the page will be treated as a GET request, resulting in an error
A route is a router
- The router is an instance of the VueRouter and contains properties and methods
- Route is the current route object, including name, Path, and Query
mixin
Event modifier
.stop
: Prevents bubbles.once
: The command is executed only once.native
: Listens for the native event of the component root element
The life cycle
beforeCreate
: called after instance initialization, data observation and before event/ Watcher event configuration.created
Data observation and event/watcher events were completed, and $el could not be retrievedbeforeMount
: called before the mount begins: relevantrender
The function is called for the first timemounted
When the instance is mounted, the DOM is the first to be retrieved$nextTick()I can do it up herebeforeUpdate
: Called when data is updatedupdated
: after the virtual DOM is re-rendered due to data changesactivated
: called when activated by a keep-alive cached componentdeactivated
: called when a component cached by keep-alive is disabledbeforeDestroy
: called before instance destructiondestroyed
: called after instance destruction
Difference between V-if and V-show
V-if: No render, meaning there is no element at all
v-show
: display:none
The priority of V-if and V-for? Why is that?
V-for has a higher priority
Why is the key passed in v-for
When v-for is used for list rendering, it defaults to the “update in place” strategy. Adding key is equivalent to adding ID to each node, so that diff algorithm can find nodes faster and more accurately for rendering
Make cross-domain requests in Vue
proxyTable: {
'/api': { // Use "/ API "instead of "http://xxxx"
target: 'http://xxxx'./ / the source address
changeOrigin: true./ / change the source
pathRewrite: {
'^/api': 'http://xxxx' // Path overwrite}}}Copy the code
NextTick principle
A deferred callback is performed after the next DOM update loop ends
Vuex
-
Introduction: Vue’s state management system, state is used to define data, actions is used to trigger the creation of mutations, mutations modify data, notify Vue to update the view
-
Usage (modular)
- The file directories are as follows:
-
Store code
// store/index.js import Vue from 'vue' import Vuex from 'vuex' import About from './about' Vue.use(Vuex) export default new Vuex.Store({ modules: { About // The module used}})// store/about/index.js import state from './state' import actions from './actions' import mutations from './mutations' import getters from './getters' export default { namespaced: true.// Enable the namespace state, // Define data mutations, // Create the action actions, // Trigger action getters // Get data } // store/about/state.js const state = { count: 0 } export default state // store/about/type.js export const ADD_COUNT = "ADD_COUNT" // store/about/actions.js import * as type from './type' // The type of action const actions = { addCount({ commit }, payload) { commit(type.ADD_COUNT, payload) // Commit triggers the mutations action. If the data is changed asynchronously, the results must be placed in actions. Payload is the data transmitted on the page}}export default actions // store/about/mutations.js // Only synchronous code can be executed import * as type from './type' const mutations = { [type.ADD_COUNT](state, payload) { state.count = payload // Payload Is the data transmitted by the action}}export default mutations // store/about/getter.js const getters = { count: state= > state.count } export default getters Copy the code
-
Use in pages
<div class="about"> <button @click="ADD_COUNT(8)">+</button> <! -- <button @click="addCount(8)">+</button> --> <br /> {{ count }} <! {{$store.state.count}} --> </div> Copy the code
// If the namespace is not enabled: Vuex provides four methods to facilitate writing import { mapActions, mapGetters, mapMutations, mapState } from "vuex"; export default { computed: { / /... MapState (["count"]),// Get state equal to $store.state.count. mapGetters(["count"]), // Getting the getter is equivalent to $store.getter.count }, methods: { The second argument is the data passed to vuex // this.$store.dispatch('addCount',8) corresponds to actions $store.com MIT ('addCount',8) corresponds to mutations. mapActions(["addCount"]), ...mapMutations(["ADD_COUNT"]),}};Copy the code
// If the namespace is enabled import { mapActions, mapGetters, mapMutations, mapState } from "vuex"; export default { computed: { / /... mapState("About", ["count"]),. mapGetters("About"["count"]),},methods: { ...mapActions("About"["addCount"]), ...mapMutations("About"["ADD_COUNT"]),}};Copy the code
The diff algorithm
Encapsulate custom directivesdirective
Slot and scope slots
<! -- Child -->
<template>
<div>
<div class="header">
<slot name="header" ></slot>
</div>
<slot name="body" :scope="{a:52}"></slot>
</div>
</template>
Copy the code
<Child>
<template #header>I am a header</template>
<template v-slot:body="{scope}">I am a body<div>{{scope}}</div>
</template>
</Child>
<! {" A ": 52} -->
Copy the code
White during solve
- An error hang
- PublicPath set
- Route mode, app is hash
- Other issues (packaging configuration, resource references…)
- The home screen is blank for a long time
- The home page loads too much data
- Join the loading
- Route lazy loading
Environment Variable Configuration
- .env.development
- .env.production
- NODE_ENV= Process.env.node_env gets script –mode development from package.json
The MVC and MVVM
- MVVM ([implementation](Object.defineProperty in #Vue2.0 and proxy in Vue3.0))
- Model: Data Model
- View: View
- ViewModel: The model is bound to the view
- MVC
- Model: Data Model
- View: View
- Controller: Bridge layer between data model and View
There is not much difference between MVVM and MVC, which are both design ideas. Controller in MVC is transformed into viewModel in MVVM. MVVM mainly solves a large number of DOM operations in MVC, which reduces page rendering performance, slows down data loading and affects user experience.
keep-alive
Cache inactive component instances
include
Components with matching names are cached.exclude
Components with matching names are not cached.max
– digital. Maximum number of component instances can be cached.
The difference between assets and static
Vue3.0
Modular API
setup
- Two parameters: props,context
- Used before the component is created
- access
this
The outputundefined
- portal
Provide/Inject optimization
To a certain extent, an alternative to Vuex might be considered
Usage:
//1. Ancestor component
/ / setup
import { provide , readonly } from 'vue'
const location = reactive({
count: 1.name: "remons"});// Set it to reactive, with the first argument: the name of the injection; Second argument: the value of the injection
provide("location", location);
// provide("location", readonly(location)); This ensures that the value will not change
// The way vUE officially recommends changing Provide is that descendant components call ancestral component methods
const changeLocation = () = > {
location.count++
};
provide('changeLocation',changeLocation)
//2. Descendant components:
import { inject } from 'vue'
// Get the ancestor passed value. The first argument is the name of the ancestor passed value. Second argument: default value
const location = inject("location");
// If you change the value here, the parent value will also change
const changeLocation = () = > {
location.count++;
};
// Vue officially recommends using the method of changing the value passed to call the ancestor component
// const changeLocation = inject(changeLocation)
Copy the code
Responsive API
reactive
readonly
Object read-only proxy (deep level)
ref
Returns a reactive and mutable REF object
Value can be used in the template, and reactive is automatically unnested
toRefs
Convert reactive objects to normal objects
Computed with the watch
-
computed
import { computed } from 'vue' const plusOne = computed(() = > count.value + 1) Copy the code
-
watch
const state = reactive({ count: 0 }) watch( () = > state.count, (count, prevCount) = > { / *... * /})Copy the code
Note: If watch listens for vuEX values, write watch before computed
watchEffect
Executes a function passed in immediately, tracing its dependencies in a responsive manner, and stops automatically when the component is unloaded
The life cycle
In addition to adding on, the destruction hook has the following transformations, which are introduced when used, and are included in setup
- beforeDestroy => onBeforeUnmount
- destroyed => onUnmounted
Add two debug hooks
- onRenderTracked
- onRenderTriggered
High order Component (HOC)
The optimization of Vue3
Other changes
teleport
To: Render node: sort of like a slot
Suspense
<Subpense>
<template #default>
<! -->
</template>
<template #fallback>
<! -- display before loading -->
</template>
</Subpense>
Copy the code
Vue3.0 combined with Vuex 4.0
// There is no big difference in the usage. When created, it is the same as vex3.0
import { createStore } from 'vuex';
export default createStore({
modules: {
// The module used}})/ / components
import { useStore, mapState, mapGetters, mapMutations, mapActions } from "vuex";
import { computed } from "vue";
export default {
setup() {
const store = useStore();
// Common usage
let detailCount = computed(() = > store.state.detail.detailCount).value,
listCount = computed(() = > store.state.list.listCount).value;
const addDetailCount = (val) = >
store.dispatch("detail/addDetailCount", val);
const addListCount = (val) = > store.dispatch("list/addListCount", val);
// Use mapState, mapGetters, mapMutations, mapActions
// const listState = mapState("list", ["listCount"]);
// const detailState = mapState("detail", ["detailCount"]);
// let listCount = computed(listState.listCount.bind({ $store: store }));
// let detailCount = computed(detailState.listCount.bind({ $store: store }));
return{}; }};Copy the code