A, instructions,
1.1 Mustache Grammar
Text interpolation with {{}}mustache syntax in VUE for data binding updates. Not only can you write variables directly, but you can also write expressions. As follows:
<div id="app"> <! Whiskers can contain variables, expressions, objects, arrays, or function returns.<div>{{msg}}</div>
<div>{{[1, 2, 3]. The map (item = > item * 2)}}</div>
<div>{{arr}}</div>
<div>{{obj.age}}</div>
<div>{{isShow?" yes":"no"}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app'.data: {
msg: 'message'.obj: { age: 20 },
arr: [1.2.3].isShow: 1}})</script>
Copy the code
1.2 Common Commands
1. V-once: An element or component is rendered only once and does not change with the data. No expression is required.
2. V-html: Double curly braces parse data to plain text, not HTML. If you’re actually printing an HTML tag you use this V-HTML directive, which is equivalent to innerHTML in JS.
V-text: equivalent to innerText in JS. Much like Mustache, it’s used to display data in the interface.
4. V-pre: VUE does not compile the label and its descendant elements with this instruction. It is mainly used to skip the compilation process of this element and its child elements to improve compilation efficiency.
V-cloak: Remain on the element until the associated instance is compiled. It is used by Vue specifically to provide instructions to solve the mustache display problem. It needs to be used in conjunction with CSS. When vue compiles, it will delete this property and CSS properties will not work.
6, v-bind(:) : to dynamically bind one or more attributes. This is often used for dynamic binding of classes or styles.
7. V-on (@) : Bind event listener. It can bind functions, objects, or expressions. If the bound method does not require additional parameters, the method () may not be added; By default, vUE passes the event object to the method if the method itself requires a parameter, and does not need to write () after the method. If the parameter is other than the method, it needs to add () and arguments after the method. If you need to pass in an argument and you also need an event event object, you can pass in the function as an argument with $event. It also contains. Stop,. Prevent,.{keyCode} and other modifiers.
V-if/V-else :Vue renders elements based on the expression’s true or false conditions. It can implement conditional rendering, which is used to control whether elements or components are loaded or not, and it has a relatively large switching overhead.
9, V-show: used to control whether elements or components are displayed. Unlike v-if, if v-if is false then the element will be destroyed and will not exist in the DOM. When v-show is false, the element will always be rendered and stored in the DOM. When v-show is false, it just adds a display: None attribute to the element to hide it. It has a relatively large initialization load overhead.
10. V-for: Used to display labels in a loop. You can loop through arrays, numbers, strings, objects (basically arrays). It usually takes a :key attribute. Keys are extremely important to Vue. It is the identity proof of the element and the unique mark of vnode in Vue. Diff operation can be more accurate and faster through key. With key, it is not local reuse and map object is generated by using the uniqueness of key to obtain the corresponding node. The key’s main purpose is to update the virtual DOM efficiently. V-if has a higher priority than V-for.
V-model: Typically used on form elements to create two-way data binding. V-model, which is essentially syntax sugar, internally uses different attributes and different events for different input elements. You can use. Lazy,. Number, and. Trim.
- The text and Textarea elements use the value attribute and input event
- The checkbox and radio use the Checked property and the change event
- Select values as prop and change events
Take the input box as an example:
<input v-model="message"/> = <input v-bind:value="message" v-on:input="message = $event.target.value" />
Copy the code
1.3 Custom Instructions
In addition to providing default built-in directives, Vue allows developers to customize directives as needed. It allows you to perform more low-level operations on DOM elements. There are two ways of global registration and local registration.
Directive (id,[definintion]). The first parameter is a custom directive name and the second parameter can be object data or a function. Note that instruction names do not need to be added with v-, which is automatic by default, but should be prefixed with V – when used. This can also be registered by adding a Cache object in the Vue instance. If there are multiple self-defined instructions in the work, they will generally create a separate file and use import or script to import them. Execute local instructions before using global instructions.
2. Computed vs Methods vs Watch
Computed: Calculates attributes. Depending on other attribute values, and computed values are cached, only when the attribute values it depends on change will computed again the next time a computed value is obtained. It’s just a function that contains set and get, but sets are usually read-only and can be deleted. So it can be used without parentheses.
computed: {
// fullName:function(){
// return this.firstName+' '+this.lastName;
// }
// Can also be written in the following form:
fullName: {
set: function (newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + ' ' + this.lastName; }}},Copy the code
Methods: This is automatically bound to an instance of Vue. There is no cache, every call is compiled to execute the function code, can’t use get, set. You can use methods in expressions to achieve the same effect as calling computed properties, typically for callback functions.
Watch: Mainly used to listen for changes in existing attributes of vUE instances (whether in data or computed), but does not work for attributes that do not exist. It is more of an observation, similar to some kind of listening callback for data, which is executed every time the listening data changes;
Application scenario:
- Use computed when you need to do numerical calculations and rely on other data. You can use computed caching to avoid recalculating every time you get a value.
- If you want to re-execute the function every time you render, use methods;
- If you need to perform asynchronous or expensive operations when data changes, you should use Watch. Using the Watch option allows us to perform an asynchronous operation, limits how often we perform that operation, and sets the intermediate state until we get the final result.
Life cycle
The Vue life cycle is the process of creating a Vue instance from the beginning, initializing data, compiling templates, mounting updated renderings, and uninstalling it from birth to death. The vue life cycle is divided into 8 phases: create before/after, load before/after, update before/after, and destroy before/after. There are different hook functions for each of these 8 phases:
- BeforeCreate stage: the mount element EL and data object data of the VUE instance are both undefined and have not been initialized.
- Created phase: Vue instance data object data, can access the data and methods in it, is not mounted to the DOM, el is not. Asynchronous requests can be written in this phase to obtain server data faster and shorten page loading time.
- BeforeMount phase: The EL and data of the vue instance are initialized, but the previously virtual DOM node is mounted.
- Mounted stage: The VUE instance is mounted to the real DOM. In this stage, the DOM can be accessed.
- BeforeUpdate phase: Called during reactive data updates, which occurs before the virtual DOM is patched and is suitable for accessing the existing DOM before updates, such as manually removing event listeners that have been added
- Updated phase: called after the virtual DOM is re-rendered and patched, the DOM is updated to avoid data manipulation in this hook function and prevent endless loops.
- BeforeDestroy stage: called before the instance is destroyed. The instance can still be used. This gets the instance
- Destroyed phase: Called after the instance is destroyed. All event listeners are removed and all subinstances are destroyed.
What are MVVM and MVC?
Model-view-viewmodel (MVVM) is a software architecture design pattern derived from the Model-View-Controller (MVC) pattern. The advent of MVVM greatly facilitated the separation of the front and back ends.
- The Model can be thought of as representing the data layer. For the front end it is the API provided by the back end;
- View represents the View layer, which is responsible for turning data into a UI for presentation. For the front end, it’s HTML and CSS;
- ViewMode is used to connect Model and View. It converts Model data obtained from the back end into data needed by View and processes the specific business logic of View layer. It is at the heart of MVVM’s thinking and is the caller to M and V, providing two-way binding of data. The View layer actually shows the data of the ViewModel layer, and the ViewModel is responsible for interacting with the Model, separating the View from the Model. Reduce code coupling, use bidirectional binding, data update after view automatic update, to automatically update the DOM.
- Its disadvantage is that bugs are difficult to be debugged, because two-way data binding is used. When bugs occur, it may be the code of view or the code of Model. For large graphics applications, there are many views and the maintenance cost is high.
It is easy to understand that the View receives the user’s interaction request, forwards the request to the ViewModel, and the ViewModel updates the data with the Model. After the Model finishes counting the data, the ViewModel notifies the ViewModel that the data has changed.
Vue’s parent and child component lifecycle hook functions are executed in the following order:
- Load the rendering
Parent beforeCreate => parent created => parent beforeMount => child beforeCreate => child created => child beforeMount => child Mounted => parent Mounted
- Subcomponent update
Parent beforeUpdate => Child beforeUpdate => Child updated => Parent updated
- Parent component update
Parent beforeUpdate => Parent updated
- Destruction of the process
Parent beforeDestory => Child beforeDestory => Child deStoryed => Parent deStoryed
V. Vue data bidirectional binding
Vue’s bidirectional data binding means that data changes automatically update the view, and the view changes to update the data. It uses data hijacking combined with the publisher-subscriber pattern to achieve bidirectional data binding. Hijack the setter/getter for the data property with Object.defineProperty. Messages are published to subscribers when data changes, triggering corresponding listening callbacks.
5.1 Object. DefineProperty & proxy
In vue2.0 we use object.defineproperty () for data hijacking. The object.defineProperty () method directly defines a new property on an Object or modifies the existing property of an Object and returns the Object. We use the getter and setter methods of accessor properties in Object.defineProperty. When a common object is passed to a Vue instance as the data option, Vue iterates over all properties in the object, adding accessor properties to it. The getter method is automatically called when reading data in the data, and the getter collects dependent data. The setter method is automatically called when modifying data in the data, notifying the view of the update, and using the getter/setter method in the object property to listen for data changes.
let obj={
name:'hello Vue'.category: {list:'Category one'.list2:'Category 2'}}; setobj(obj);function defineProperty(obj,k,val){
if(typeof val =="object"){
setobj(val);
}
Object.defineProperty(obj,k,{
get(){// Rely on collection
return val;
},
set(val){ // Notify the view of updatesval = v; }})}function setobj(obj){
Object.keys(obj).forEach(k= >{
defineProperty(obj,k,obj[k])
})
}
Copy the code
With Object.defineProperty(), it converts the key of the Object into a getter/setter to track changes. Getter /setter only tracks whether a data has been modified, not additions or deletions of attributes. $Vue.$set = Vue.$set = Vue.
Couldn’t listening to the array Object. DefineProperty () method, for the array, the following methods in the Vue push, pop, shift, unshift, splice, sort, reverse is through the internal processing to rewrite array to ensure the response type. And Object.defineProperty() can only hijack attributes of an Object, requiring deep traversal if the attribute value is also an Object. By looking at the source code section of Vue, we can see that Vue overrides arrays and iterates through objects recursively, so that object.defineProperty () can also listen on objects and arrays (partial method operations). This is very troublesome, so VUe3.0 uses proxy proxy to implement data hijacking. Proxy is an enhanced version of Object.defineProperty. It intercepts objects before they are accessed. It provides a mechanism for filtering and rewriting access to objects.
Proxy allows you to listen directly on objects (rather than on object properties) and also on array changes. As follows:
let obj = {
like: 'swam'.age: { age: 20 },
arr: [1.2.3.4]};function render() {
console.log('render')}let handler = {
get(target, key) {
// Determine whether the selected value is an object
if (typeof target[key] == 'object'&& target[key] ! = =null) {
return new Proxy(target[key], handler);
}
return Reflect.get(target, key);
},
set(target, key, value) {
if (key === 'length') return true
render();
return Reflect.set(target, key, value)
}
}
let proxy = new Proxy(obj, handler)
proxy.age.name = 'davina' // New attributes are supported
console.log(proxy.age.name) // Update the mock view "davina"
proxy.arr[0] = '100' // Support changes in the contents of arrays
console.log(proxy.arr) //Proxy {0: "100", 1: 2, 2: 3, 3: 4}
Copy the code
From the above we can see that proxy can listen directly for objects instead of properties and it can listen directly for array changes and return a new object, so we can just manipulate the new object to do that. Object. DefineProperty can only be directly modified by traversing Object attributes, which is compatible with IE9, while proxy has browser compatibility problems.
When a data attribute changes, we can notify the places where the data has been used. How do we know which places the data has been used? How do we make the notification?
We need to collect the dependencies to know where to rely on the data and update the data when it is updated. This is where the publish-subscribe model comes in.
5.2 Publish and subscribe Mode
To understand the publish-subscribe model we need to understand what the observer model is. The observer pattern defines a one-to-many dependency between objects. When an object’s state changes, all dependent objects are notified and updated accordingly. As shown in the figure below, an Observer can subscribe directly to a subject, and when the subject is activated, it fires events in the observer. The observer generally provides an update interface, which is used to get timely notification when the state of the observed changes, so as to make a response. For the observed, what it needs to do is to timely notify the observer when the state changes.
The Observer pattern was previously called publish subscribe, but as project complexity and code maintainability increased, the two generally moved in the same direction, but in many ways they were not equal. In real development we use publish-subscribe more.
In the current publish-subscribe model, messages sent by publishers are not sent directly to subscribers, but are contacted through a third-party component middleware. Publishers and subscribers are unaware of each other’s existence and communicate through middleware. As can be seen from the following figure, Subscriber registers the events they want to Subscribe to the middleware (Event channel), Publisher publishes events to the middleware. The processing code that subscribers register with the dispatch center is unified by the middleware for fire events.
The biggest difference between the two is that there is an event call center in the publish-subscribe model, the middleware. The observer mode is scheduled by the specific target, and each subscribed target needs to have observer processing. This is simple and efficient, but causes redundancy in the code. Poor maintainability. As for the publish-subscribe model, it is handled uniformly by the middleware of the dispatch center, and subscribers and publishers do not interfere with each other, eliminating the dependence of the two and realizing the decoupling. But the lack of awareness among publishers and subscribers can sometimes cause problems.
5.3 Bidirectional binding in VUE
Bidirectional binding of Vue data is implemented through the following steps:
Implement a listener Observer
Vue uses an Observer to implement listening, which hijacks and listens to all properties, notifying the subscriber Watcher if the properties change. The Object. DefineProperty method is mainly used in Vue2.0 to traverse data objects, while the proxy proxy is used in Vue3.0.
/* Listener */
function observe(data) {
// Simply determine the type
if (typeofdata ! = ='object') {
return;
}
let keys = Object.keys(data);// Key is an array of all attribute names
keys.forEach(key= > {
defineReactive(data, key, data[key])
})
}
// Encapsulate a defineReactive function that specifically calls defineProperty to implement data hijacking
function defineReactive(obj, key, value) {
observe(value);// Implement deep hijacking
let dep = new Dep;// Each key has a private variable dep
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target);// dep. target is an instance of Watcher
}
return value;
},
set(newval) {
if(value ! == newval) { value = newval; observe(value); dep.notify(); }}})}Copy the code
Implement a subscriber Dep
Subscriber Dep uses published-subscription mode to collect subscriber Watcher, and manages listener Observer and subscriber Watcher uniformly. Simply put, a Dep is a place to store dependencies, which can be used to collect them, delete them, send messages to them, and so on. Its primary role is to hold the Watcher observer object, which we can think of as an intermediary, notifying it when data changes, and then notifying it elsewhere. We can call addSub when a requirement collects dependencies and notify when a requirement sends out updates.
/ / subscriber
class Dep {
constructor() {
// Provide an event pool
this.subs = [];
}
// Add events to the event pool
addSub(sub) {
this.subs.push(sub);
}
// Notification update
notify() {
this.subs.forEach(item= > {
// Make the corresponding event do the update operationitem.update(); }}})Copy the code
3, implement a subscriber Watcher
The Watcher subscriber is the communication bridge between the Observer and Compile. Its main task is to subscribe to the message of the change of attribute value in the Observer. When the change of attribute value is received, the corresponding update function in the parser Compile is triggered. When the property changes, we need to notify all the places where the data is used. There are many places where the data is used in a project or file, and the types are not necessarily the same. At this point, we need to abstract out a class set for processing. In the dependency collection phase, we only collect the instance of the encapsulated class, notify it only, and then it is responsible for notifying other places, which is much faster and efficient. The purpose of dependency collection is to store the Watcher subscriber object under the SUBs of the Dep subscriber in the current closure.
/* A simple implementation of Watcher */
class Watcher {
constructor(obj, key, cb) {
// Point dep. target to yourself
Dep.target = this
this.cb = cb
this.obj = obj
this.key = key
this.value = obj[key]
// Dep. Target is left blank
Dep.target = null
}
update() {
// Get a new value
this.value = this.obj[this.key]
// We define a cb function that simulates view updates
this.cb(this.value)
}
}
Copy the code
4. Implement a parser Complie
Compile parses the template instructions, replaces variables in the template with data, initializes the render page view, and binds the corresponding node of each instruction to update function, adds subscribers to listen to the data, receives notification once the data changes, and updates the view.
A complete bidirectional binding has the following points:
1. After new Vue(), use Proxy or object.defineProperty to “hijack” the attributes of the Object/Object. Data in Vue is added with getter/setter attributes via Observe. Getter functions are executed when an object is read and setter functions are executed when a value is assigned. Notify subscribers of property changes;
Compile parses the instructions in the template, collects methods and data, waits for the data to change and then renders;
3. Watcher receives data changes generated by Observe and renders the view according to the instructions provided by Compile, so that data changes promote the view changes.
Vi. Virtual DOM in VUE
Virtual DOM (Virtral DOM) is one of the cores of Vue, which is often referred to as virtual node. It simulates DOM nodes through javascript Object and then renders them into real DOM nodes through specific methods. The virtual DOM will not be rearranged or redrawn, and it can modify the part of the real DOM that needs to be changed at one time, which can minimize the operation of the real DOM, which can reduce the page backflow and redraw greatly improve the page performance.
Virtual DOM(VDOM) is a tree-like structure. Its node is VNode, which exists only in vDOM tree. The corresponding real DOM node can be accessed through the ELM attribute of Vnode. It actually uses THE JS object structure to represent the structure of the tree, and then the tree builds a real DOM tree and inserts it into the text. When the state is updated, a new object tree is reconstructed, the old and new trees are compared, and then the difference is applied to the real DOM tree constructed, so as to achieve the update operation of the view.
There are a number of processes and steps to go from the virtual DOM to the real DOM. When the getter and setter in Object.defineProperty are used to realize data hijacking operation, the virtual DOM simulates the real DOM structure, and the render algorithm is used to parse the virtual DOM and render it into the real DOM. When the data changes, setter will be triggered, and the corresponding dep. notify function will be executed. At this time, virtual DOM will be generated again, and the diff algorithm will be used to calculate the minimum unit of modification, generate patch patch, and re-render the real DOM.
We can see that the virtual DOM has three key points:
- JavaScript objects simulate real DOM trees and abstract the real DOM.
- Diff algorithm is used to compare the differences between two virtual DOM trees.
- Patch algorithm applies the difference between two virtual DOM objects to the real DOM tree
Seven, components,
7.1 Component Classification
Component is a very bright part in Vue. Componentization is an important idea in Vue. Any application can be abstracted into a Component tree, which is very flexible for reuse.
Component use is divided into three steps:
- Create a component constructor object
Call the vue.extend () method to create the component constructor, which is the built-in method in Vue. Normally, when creating the component constructor, we pass in the template representing our custom component template. This template is the HTML code to display where the component is used:
// 1. Create a component constructor object
const cpnC = Vue.extend({
/ / template
template: '
< H2 > Hello, Li Yinhe
< H3 > I am Wang Xiaobo
'
})
Copy the code
- Certified components
- Global registration: Vue.component(tagName,options) to register. Where tagName is the tagName of the registered component, it cannot be an existing HTML tag, it is better to use – to represent the connection, options component constructor. After the component is registered, it can be used as a custom element in the parent instance’s template. The global registry component can be used in the template of any newly created Vue root instance.
- Local registration: This is done by using the component instance option Components to make components available only in one instance or in the scope of the component. It is registered in whichever component it wants to use.
// Global register:
Vue.component('my-cpn1-tagName',cpnC);
// Local registration:
const app = new Vue({
el:'#app'.components: {'my-cpn2-tagName':cpnC
}
})
// Syntax sugar is now commonly used
Vue.component('my-cpn1-tagName', {template: '
< H2 > Hello, Li Yinhe
< H3 > I am Wang Xiaobo
'
});
const app = new Vue({
el:'#app'.components: {'my-cpn2-tagName': {template: '
< H2 > Hello, Li Yinhe
< H3 > I am Wang Xiaobo
'}}})Copy the code
- Use components: Use them in templates
<div id="app">
<my-cpn2-tagName></my-cpn2-tagName>
</div>
Copy the code
We can use the
tag to separate the template to make the structure clearer, as follows:
</h3> </div> '</template> Vue.component('my-cpn1-tagName','#cpn1'); Const app = new Vue({el:'#app', Components :{' my-cpn2-tagname ':{template: '#cpn1'}}})Copy the code
Typically we pass data through vUE component objects. When a component is defined, data needs to be declared as a function that returns an initial object.
//data
data(){
return {
message:""}}// new Vue
new Vue({
el:"#app",
data{
message:""}})Copy the code
Because a component can be used to create multiple instances, it is intended for reuse. If data is just an object as before, all instances will use the same data object. The JS object is a reference, and the scope is not isolated. The data property values in the child components affect each other. However, if data is a function, it can guarantee data independence. After each instance is created, the data function can be called, so that each instance can maintain an independent copy of the returned object, and the data attribute values between instances will not affect each other.
7.2 Component Communication
There are three communication modes in Vue: parent-child component communication, sibling component communication, and intergenerational component communication.
7.2.1 props
Validation and$emit
The parent component passes data to the child component through custom properties and props. The child component passes data to the parent component, or when the parent wants to use data or methods from the child component, it can use custom events and $emit. As follows:
App component: <template><div>
<child :fatherToChild="message" @btnClick="btnClick"></child>
<button v-for="item in data" :key="item.id">{{item.name}}</button>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {
message: "I'm Wang Xiaobo.".data: {}}; },components: {
Child,
},
methods: {
btnClick(value){
this.data = value
}
},
};
</script>Child component: <template><div>
<h2>{{ fatherToChild }}</h2>
<button @click="btnClick">btn</button>
</div>
</template>
<script>
export default {
name: "child".// Porps for child components
props: {
fatherToChild: {
type: String.required: false.default: "hello world",}},data() {
return {
mes: "Data in child components".categories: [{id: "0001".name: "Top recommendations" },
{ id: "0002".name: "Mobile Digital"},]}; },methods: {
btnClick(){
// Emit a custom event for the parent component to receive
this.$emit('btnClick' ,this.categories)
}
},
};
</script>
Copy the code
Prop is one-way downlink binding and one-way data flow. That is, when the parent component’s prop changes, it is passed to the child component, but not the other way around. This prevents accidental changes in the state of the parent component from the child component. Update whenever the parent component, it can through the custom properties and prop to transfer data subcomponents, subcomponents prop will be updated with the latest value, this means that should not be in the interior of the child components change prop, if really want to change should also be distributed to every parent component child components through $emit a custom event, after receiving the parent components, Modified by the parent component.
7.2.2 ref
和$parent
with$children
The parent can access the child via $ref or $children
Ref refers to a DOM element if used on a normal DOM element, and to a component instance if used on a child component. The functions of ref are as follows:
- This.$refs.box retrieves the DOM element
- This.$refs.box. MSG gets the data in the child component
- This.$refs.box.open() invokes methods in child components
Parent component: <template><div>
<button @click="fatherToSon">Parent operator child: BTN</button>
<child ref="son" />
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {};
},
components: {
Child,
},
methods: {
fatherToSon() {
this.$refs.son.showMessage(); ,}}};</script>Child components:<template>
<div ref="box"></div>
</template>
<script>
export default {
name: "child".data() {
return {
mes: "Display by clicking the BTN button in the parent component."}; },methods: {
showMessage() {
this.$refs.box.innerHTML = this.mes; ,}}};</script>
Copy the code
$children is an array type that can be indexed to find the corresponding child component. In the case of $children, it is neither responsive nor guaranteed order. $parent gets the parent of the current component, and $root gets the root component. None of these are commonly used.
Parent component: <template><div>
<button @click="fatherToSon">Parent operator child: BTN</button>
<child />
<child />
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {
mes: "New news"}; },components: {
Child,
},
methods: {
fatherToSon() {
// Parent operator child:
this.$children[1].$el.innerHTML = this.mes; ,}}};</script>Child component: <template><div>
<div>{{ mes }}</div>
<button @click="sonToFather">BTN of the child component</button>
</div>
</template>
<script>
export default {
name: "child".data() {
return {
mes: "Display by clicking the BTN button in the parent component."}; },methods: {
sonToFather() {
// Access the parent component and call its methods
console.log(this.$parent.fatherToSon()); ,}}};</script>
Copy the code
7.2.3 $attr
& $listeners
$attrs: When a component does not declare any prop, it contains all of the parent scope’s bindings and can be passed to the internal component by v-bind:=’$attrs’, often used in conjunction with the inheritAttrs option.
$Listeners: Contains THE Parent component’s V-O event listeners, which can be passed into the internal component via V-on =”$Listeners”
7.2.4 dojo.provide & inject
If an ancestor element provides a variable via provide, all its descendants can obtain the provided properties via Inject provide. It mainly addresses communication between components.
7.2.5 EventBus
This approach uses an empty Vue instance as the central event bus (event hub), which triggers events and listens for events to communicate between any component, including parent, generational, and sibling components.
7.2.6 vuex
When we need to communicate too much data, we can use VUEX to process the data.
7.3 slot.
Component slots are designed to make the components we package more extensible. It is used to decide what to insert into the specified location. Let the user decide what some of the content inside the component actually shows.
- Anonymous Slot: This is also called the default slot. When the child component template only has a slot without any attributes, the entire content segment of the parent component is inserted in the slot’s location and the slot label is replaced, which can be placed anywhere in the child component. As follows:
App parent <template><div>
<h4>Here is the parent component, which has a child component that is used multiple times</h4>
<child>
<h3>{{ mes }}</h3>
<h4>The content is inserted</h4>
</child>
<child></child>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {
mes: "New news"}; },components: {
Child,
},
methods: {}};</script>Subcomponents < template ><div>
<div>{{ mes }}</div>
<! -- This is anonymous slot -->
<slot>
<! -- Replace slot with content in the parent component if there is no content in the slot -->
<p>When nothing is inserted in the parent component, I am the default</p>
</slot>
</div>
</template>
<script>
export default {
name: "child".data() {
return {
mes: "I am a child component"}; },methods: {}};</script>
Copy the code
- Named Slot: When there are multiple slots, we can use the name attribute to insert content into different slot configurations. The named slot will match the element of the slot property when the content snippet is used. It can also be operated with v-slot.
V - slot: slot
Is equivalent to< tag name slot =" slot name ">
It can only be used on templates.
App
<template>
<div>
<h4>Here is the parent component</h4>
<child>
<span slot="center">I want to replace the middle one</span>
<span>Other content</span>
</child>
<child>
<template v-slot:center>
<span>In the middle</span>
</template>
</child>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {
mes: "New news"}; },components: {
Child,
},
methods: {}};</script>Child component: <template><div>
<div>{{ mes }}</div>
<slot name="left"><span>left</span></slot>
<slot name="center"><span>center</span></slot>
<slot name="right"><span>right</span></slot>
</div>
</template>
<script>
export default {
name: "child".data() {
return {
mes: "I am a child component"}; },methods: {}};</script>
<style scoped>
span {
padding: 0 10px;
}
</style>
Copy the code
- Scope slot: this is a special slot that can carry data. Before we understand scope slots, we need to understand what a compilation scope is. A compilation scope simply means that everything that can be viewed as a parent component template is compiled in the parent scope; Everything in a child component template is compiled in a child scope, and a scope slot lets the parent component replace the slot’s label, but the content is not supplied by the child.
App parent <template><div>
<h4>Here is the parent component</h4>
<child></child>
<child>
<! -- Old version: Slot-scope name optional -->
<template slot-scope="slot">
<span>{{ slot.data.join(" - ") }}</span>
</template>
</child>
<child>
<! -- New version -->
<template #default="slot">
<span>{{ slot.data.join("*") }}</span>
</template>
</child>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "father".data() {
return {
mes: "New news"}; },components: {
Child,
},
methods: {}};</script>Child component: <template><div>
<div>{{ mes }}</div>
<! -- Name is optional -->
<slot :data="data">
<ul>
<li v-for="item in data" :key="item">{{ item }}</li>
</ul>
</slot>
</div>
</template>
<script>
export default {
name: "child".data() {
return {
mes: "I am a child component".data: ["vue"."react"."angular"]}; },methods: {}};</script>
<style scoped>
span {
padding: 0 10px;
}
</style>
Copy the code
Eight, what is SPA?
SPA (Single-Page Application) loads the corresponding HTML, JavaScript, and CSS only when the Web page is initialized. Once the page is loaded, SPA will not reload or jump the page because of the user’s operation. Instead, routing mechanisms are used to transform HTML content, interact with the user and avoid page reloading.
Advantages:
- User experience good content changes do not need to reload the entire page, avoiding unnecessary jumps and repeated rendering;
- The responsibilities of the front and back end are separated, and the architecture is clear. The front end carries out interactive logic, and the back end is responsible for data processing.
Disadvantages:
- Time-consuming initial loading: To achieve single-page Web application functions and display effects, JavaScript and CSS must be loaded uniformly during page loading, and some pages must be loaded on demand.
- SEO is difficult: because all the content is displayed in a dynamic replacement page, it has a natural disadvantage in SEO optimization.
Supplement:
- Back-end rendering: In the development of early websites, the entire HTML page is rendered by the server. The server directly produces and renders the corresponding HTML page and returns it to the client for display. In this case, the rendered page does not need to load any JS and CSS separately and can be directly handed to the browser for display. Good for SEO optimization but bad for authoring and maintenance puts a lot of strain on the server.
- Front-end rendering: The front-end and back-end are separated through Ajax, and the latter is only responsible for providing data without providing any interface content. Most of the content of the web page displayed in the browser is executed by the front-end JS code in the browser, and finally rendered out of the web page. This creates a clear division of responsibility at the front and back ends, with the back end focused on data and the front end focused on interaction and visualization.
- SPA: Single page rich application
Nine, Vue – the router
Routing is the activity of transmitting information from source address to destination address over an interconnected network. Routing is essentially a mapping table that determines the path of packets from source to destination and the transfer of data from the input end to the appropriate output end.
9.1 Routing Mode
Vue-router has three routing modes: hash, history, and Abstract.
- Hash pattern
The early front-end routing was implemented with location.hash. The value of location.hash is what comes after the # in the URL. The hash value is just a state of the client. When we change the hash value with location.hash, no request is sent to the back end, that is, no page refresh, and no hash part is sent to the back end. Each time we modify the hash, we add a record to the browser’s history (or use history.pushState()), so we can control the hash switch by backing up the browser. It is generally possible to jump the page with history.go(),history.forward(), and use hashchange events to listen for hash changes to jump the page (rendering). The hash mode is compatible with all browsers.
- The history mode
It relies heavily on the HTML5 apis history.pushstate () and history.repalcestate (). Both apis allow you to manipulate the browser’s history without refreshing it. The only difference is that the former is to add a history, the latter is to directly replace the current history. They can both manipulate urls to jump to pages, and we can listen for url changes through popState events.
- The abstract model
It supports all JS runtime environments and automatically enters this mode if the browser API does not exist.
9.2 Using Routes
Build:
- Installation and Introduction
- Install the plug-in through vue.use ()
- Create the VueRouter object export to be used in the Vue instance
NPM install vue-router(modularization only)
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '.. /views/study/Home.vue'
import Home from '.. /views/study/User.vue'
// 2. Install plug-ins
Vue.use(VueRouter)
// create the VueRouter object
const routes = [{
path: '/'./ / redirection
redirect: '/home'
},
{
path:'/home'.name:'Home'.component:Home,
// Route nesting
children:[
{
path:'detail'.name:'User'.component:User
}
]
}]
const router = new VueRouter({
// Configure the relationship between routes and components
routes,
// The default hash mode is #, you can use the history mode in this mode
mode: 'history'.linkActiveClass: 'active'.base: process.env.BASE_URL,
})
// The export is used in the instance
/ / export:
export default router
// Use: main.js
new Vue({
router,
render: h= > h(App)
}).$mount('#app')
Copy the code
Steps to use vue-Router:
- Creating a Routing Component
- Configuring Route Mapping
- Use routes. through
<router-link>
和<router-view>
<router-link>
: It is a built-in component of vue-Router and will be rendered as an A tag<router-link>
There are a few other attributes:<router-link to='/home' tag='li' replace>
to
: Specifies the jump pathtag
: Tag can be specified<router-link>
The code above will be rendered as a LI tag instead of an A tag;replace
Replace does not leave a history, so if replace is specified, the back key cannot return to the previous page.active-class
: When the route matches successfully, the system automatically sets a router-link-active class for the current element. You can change the default router-link-active class name.
<router-view>
: It is also a built-in component that dynamically renders different components based on the current path. Other content of the page, such as the title/navigation at the top, or some copyright information at the bottom, will be at the same level. During route switchover, mounted components are switched, and other contents remain unchanged.- You can also modify the route in code:
This.$router. Push () or this.$router. Replace ().
. The Router object is a VueRouter instance of a global router, including route hops, hook functions, and so on. The Route object represents the current route information, which route is active. Contains information obtained from the current URL resolution. Contains the current path, parameters, query objects, and so on.
9.3 Dynamic Routing & Transfer Parameters
We sometimes need to match a pattern to all routes, all mapped to the same component, generally used for dynamic route parameters.
Types of params:
- Configure the route format as /about/: ID
- Pass method: Follow path with the corresponding value
- Pass path: /about/0001
The routing configurationconst router = new VueRouter({
routes: [
// Dynamic path parameters start with a colon id is a dynamic value
{ path: '/about/:id'.componentAbout}]}) App component: <! -- Params pass parameter: dynamic routing --><router-link :to="'/about/' + userData.userId">about</router-link>
<h3>{{$route.params.id}}</h3>
Copy the code
The query type:
- Configure the route format: /about, that is, the common format
- Pass method: The object uses the Query key as the pass method
- The path formed after passing: /about? id=0002
The routing configurationconst router = new VueRouter({
routes: [{
// Use query to pass parameters
path: '/about'.name: 'About'.componentAbout,}]}) App component: <! -- Params pass parameter: use V-bind and object --><router-link :to="{ path: '/about', query: { id: '002', name: 'amy' } }">about</router-link>
<h3>{{$route.query.id}}</h3>
Copy the code
9.4 Lazy Route Loading
Lazy loading of routes is to divide the components corresponding to different routes into different code blocks, and then load the corresponding components when the routes are accessed. In this way, when webpack is packaged, js files will not be too large, resulting in a large waiting time for users to enter the home page, resulting in a white screen effect. It is actually load on demand, effectively share the pressure of the home page, can reduce the load time of the home page. Use as follows:
const router = new VueRouter({
routes: [{path: '/home'.component: () = > import(/* webpackChunkName: "group-foo" */ './Foo.vue')}]})Copy the code
9.5 Navigation Guard
The navguard can perform some necessary authentication, such as login authentication, before a route can jump. The navigation guard has:
- Global route guard: can be used to check and verify user login
- Global front guard
router.beforeEach
- Global post-hook
router.afterEach
- Global front guard
- Route exclusive guard
beforeEnter
: Used for route configuration - Its own guard within the component: It can be used directly within the component as a lifecycle, such as asking for information when the user leaves the current interface
beforeRouteEnter
.BeforeRouteUpdate (2.2 New)
beforeRouteLeave
.
// Verify login
// From from to next() must call this method to resolve the hook
// Make sure that the next function is called exactly once in any given navigator. It can occur more than once, but only if all logical paths do not overlap, otherwise the hook will never be parsed or an error reported
router.beforeEach((to, from, next) = > {
if (to.path === '/login') return next();
let str = localStorage.getItem('user')
if(! str)return next('/login')
next()
})
Copy the code
9.6 keep-alive
Keep-alive is a component built into Vue that does not generate a real DOM node. It allows the contained components to remain in state, caching inactive component instances and avoiding re-rendering.
- It is used together with routing and dynamic components to cache components.
- Includes include and exclude attributes, both of which support strings or regular expressions (define a cache whitelist, and keep-alive will cache hit components), and exclude (exclude, which is not cached). Exclude has a higher priority than include.
- The hook function activated is activated when a component is activated, and the hook function deactivated is activated when a component is removed.
Ten, vuex
Vuex is a state management tool designed specifically for vue.js applications. Centralized storage is used to manage the state of all the components of the application, and rules are used to ensure that the state changes in a predictable way. Generally speaking, when there are many components and they need to communicate with each other, Vuex can be used to save the shared state of multiple components. In this case, only state is required to synchronize state between components.
Vuex is characterized by separate isolation of data into a tree graph, which indicates that it has its own ecosystem, with action as data input and State as data output. State can only be modified in mutations, but state cannot be directly modified in actions. In mutations, modify the data of state, which can only be a synchronous operation, not an asynchronous operation (but if it is asynchronous, it will not report an error, but it is not recommended). If it is an asynchronous operation, you can put the operation in action, get the data and process it synchronously through mutations.At the heart of every Vuex application is the Store. Store Is a container that contains most of the state in an application. Vuex’s state store is responsive. When the VUE component reads state from store and the state changes, the corresponding component changes and updates. State in the repository cannot be changed directly. The only way to change state is to display mutation. This makes it easy to track each state change.
It mainly contains the following modules:
- State (data) : The data structure that defines the application state, where the default initial state can be set. Each application will contain only one Store instance. It’s a public state;
- Getter: is the computed property of the store. Sometimes a requirement derives state from state in a store, so a getter is used, and the value returned by the getter is cached based on the dependency and recalculated only when its dependency value changes. Use the $store.getters. Property name. It can take arguments or no arguments and accept state as its first argument or another getter as its second argument. It can be regarded as processing the data source and returning the required data;
- Mutation (execution) : The only way to change store state in VUEX is commit(mutation). Mutation in VUEX is similar to events. Each mutation has an event type (type) and a callback function (handler). This callback function is where the actual state change occurs, which can be thought of as {type:handler()}, The store.mit method is used when type is called. Mutation must be synchronous for debugging convenience. When used in projects, constants are usually kept in separate files, which is more conducive to collaborative development and efficiency.
- Action (event) : This is set for asynchronous operations. Since mutation can only be a synchronous operation, but there will be asynchronous operations in a real project, actions is the operation to be performed and can be synchronized or asynchronous
- Module: Allows you to split a single Store into multiple stores and Store them simultaneously in a single state tree.
So in a nutshell, vuEX’s workflow is as follows:
- Submit an Actions via Dispatch
- Actions receives this event, and can perform some asynchronous or synchronous operations in the Actions to distribute to different mutations depending on the situation
- Actions trigger mutations by committing;
- Mutations updates the data in state, and after state is updated, it will be rendered through VUE