Vue request mode
First encapsulation axios
import axios from "axios";
const const setDefaultParams = params= > {
return params;
}
const resolve = function (response, success, error) {
const status = response.statue || response.status
if (String(status) === '0') {
success(response)
} else {
// console.log('api error=====', response)
if (error) {
error(response)
} else{}}}const reject = function (response, error) {
console.error('API Error')
if (error) {
error(response)
}
}
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
});
// request interceptor
service.interceptors.request.use(
config= > {
// do something before request is sent
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers["X-Token"] = getToken();
}
return config;
},
error= > {
// do something with request error
console.log(error); // for debug
return Promise.reject(error); });// response interceptor
service.interceptors.response.use(
/** * If you want to get http information such as headers or status * Please return response => response */
/** * Determine the request status by custom code * Here is just an example * You can also judge the status by HTTP Status Code */
response= > {
const res = response.data;
// if the custom code is not 20000, it is judged as an error.
if(res.code ! = =20000) {
Message({
message: res.message || "Error".type: "error".duration: 5 * 1000
});
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm(
"You have been logged out, you can cancel to stay on this page, or log in again"."Confirm logout", {
confirmButtonText: "Re-Login".cancelButtonText: "Cancel".type: "warning"
}
).then(() = > {
store.dispatch("user/resetToken").then(() = > {
location.reload();
});
});
}
return Promise.reject(new Error(res.message || "Error"));
} else {
returnres; }},error= > {
console.log("err" + error); // for debug
Message({
message: error.message,
type: "error".duration: 5 * 1000
});
return Promise.reject(error); }); service.get =(path, params, success, error) = > {
const paramsData = Object.assign({
t:new Date().getTime()
},params)
params = setDefaultParams(paramsData)
const res = service({
url: path + '? ' + qs.stringify(params),
method: 'get'.data: params,
transformRequest: function (obj) {
let ret = ' '
for (const it in obj) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(obj[it]) + '&'
}
return ret
},
headers: {
'Content-Type': 'application/json'
}
})
res.then(
response= > {
resolve(response, success, error)
},
response= > {
reject(response, error)
}
)
}
service.put = (path, params, success, error) = > {
const paramsData = Object.assign({
t:new Date().getTime()
},params)
params = setDefaultParams(paramsData)
const res = service({
url: path + '? ' + qs.stringify(params),
method: 'put'.data: params,
transformRequest: function (obj) {
let ret = ' '
for (const it in obj) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(obj[it]) + '&'
}
return ret
},
headers: {
'Content-Type': 'application/json'
}
})
res.then(
response= > {
resolve(response, success, error)
},
response= > {
reject(response, error)
}
)
}
service.post = (path, params, success, error) = > {
params = setDefaultParams(params)
const res = service({
url: path,
method: 'post'.params: params
})
res.then(
response= > {
resolve(response, success, error)
},
response= > {
reject(response, error)
}
)
}
service.postJson = (path, params, success, error) = > {
params = setDefaultParams(params)
const res = service({
url: path,
method: 'post'.data: params,
transformRequest: function (obj) {
return JSON.stringify(obj)
},
headers: {
'Content-Type': 'application/json'
}
})
res.then(
response= > {
resolve(response, success, error)
},
response= > {
reject(response, error)
}
)
return res
}
export default service;
Copy the code
API Management Interface
import request from '@/utils/request'
export function fetchArticle(id) {
return request({
url: '/vue-element-admin/article/detail'.method: 'get'.params: {
id
}
})
}
Copy the code
Component interface calls
import { fetchArticle } from '@/api/article'
fetchArticle(id).then(response= > {
this.postForm = response.data
// just for test
this.postForm.title += ` Article Id:The ${this.postForm.id}`
this.postForm.content_short += ` Article Id:The ${this.postForm.id}`
// set tagsview title
this.setTagsViewTitle()
// set page title
this.setPageTitle()
}).catch(err= > {
console.log(err)
})
Copy the code
In the actual development process, when a GET request is found, the Internet Explorer and Firefox get request will be cached after the first request. To solve the problem, we need to splicing time after THE URL. If we request in the current way, we need to splicing time in each request, which is not very convenient. In order to achieve global management, we change the request mode. To use it, you need to mount utils/index.js globally
import axios from './axios'
export default {
install: (Vue) = > {
// Bind to the prototype chain of the vue instance so that you can call this.$axios.get() directly from the component without importing the AXIos module
Vue.prototype.$axios = axios
}
Copy the code
Intra-component invocation
methods: {
getList() {
const uid = this.storage.get('yh-user').userId
this.$axios.get(
'/EipCountAction/getTaskCount.do',
{ userId: uid },
res= > {
this.numb = res.dataContent
}
)
}
}
Copy the code
This request, do not need each interface to splice, before the request to get unified splicing time rub
const paramsData = Object.assign({
t:new Date().getTime()
},params)
params = setDefaultParams(paramsData)
Copy the code
The new list field on the request backend cannot be updated
This.$set() ¶
this.solutionList = r.data.data.solution;
for(let i=0; i<this.solutionList.length; i++){// There is no get/set and no response
// this.solutionList[i].is = true;
this.$set(this.solutionList[i],'is'.false);
}
Copy the code
- Vue array adds a new field, change the value of the field does not change;
- Provides solutions;
- Vue2.0 adds attributes to data objects and triggers view updates;
- Elaborate on
this.$set()
The correct use of;
- Elaborate on
- Real-time response to failure issues after adding new attributes to vUE data;
- Data updates are needed
geter()/seter()
Two methods;
- Data updates are needed
Correct understanding
listeners
Data communication between Vue components is described as follows:
In fact, there are other ways to communicate with data, such as the parent component getting the child component data and events, through:
- Get the child component instance by binding the ref property to the child component
- Get the child component instance with this.$children
For child components to get parent component data and events, you can do this:
- Parent component data and events are passed through props, or event passing is implemented through emit and emit and emit and on
- Through the ref attribute, call child component methods and pass data; Parent component data and events are passed through props, or event passing is implemented through emit and emit and emit and on
- By enclosing the parent, the parent. The parent. The data or enclosing parevent. The data for the parent component data, by enclosing parevent. _data while forming for the parent component data, by enclosing parevent. The data for the parent component data, Execute the parent component method with this.parent
For data communication and event passing between sibling components, you can use:
- Mount global events using eventBus
- Use parent to pass data, parent to pass data, parent to pass data, parent.$children to call sibling events
In addition, more complex, Vue component data communication can be done through Vuex. In particular, data communication between multi-level nested components. But using Vuex is a bit wasteful if you’re just passing data from one data to another without doing any intermediate processing. However, since Vue 2.4, there is an alternative:
Use v-bind=”$attrs” to pass attributes from the parent component that are not considered bound to the props feature to the child component.
Typically this method is used in conjunction with interiAttrs. They are used this way because they make communication between components across components simple and business clear without Vuex and eventBus. In fact, that’s another thing we’re going to look at today. How attrs and Attrs and Attrs and Listeners can communicate data between multiple levels of nested components.
The business scenario
As mentioned, we are going to talk about data communication between multi-level nested components. To keep things from getting too complicated (too complex for beginners to understand and learn). Let’s take nesting between three levels of components as an example. ComponentA > ComponentB > ComponentC (ComponentA > ComponentC)
In terms of three-level nested components, their relationship is relatively simple:
- ComponentA is the parent component of ComponentB, and their relationship is the parent-child relationship
- ComponentB component is the parent component of ComponentC component, and their relationship is also the parent-child relationship
- ComponentA component is the ancestor component of ComponentC component, and their relationship is the ancestor and grandson relationship
For the data communication between these three components, according to our previous knowledge, it is expected that:
Props down, $emit up.
That is to say, ComponentA to ComponentB can pass to sub-components in the way of props, and ComponentB to ComponentA through ComponentB component
The on mode listens for sent events. A similar approach can be used for communication between ComponentB and ComponentC. But for the communication between ComponentA component and ComponentC component, need to use ComponentB component as a transfer station, when ComponentA component needs to pass the information to ComponentC component, ComponentB accepts the information of ComponentA component, The properties are then passed to the ComponentC component.
This is a solution in this sense, but if we have too many layers of nested components, the code will be cumbersome and difficult to maintain.
In addition to the above methods to complete data communication between components, there are other methods, such as Vuex global state sharing; Use eventBus to create an instance of Vue to realize the monitoring and publishing of events, so as to achieve data communication between components. But they are too wasteful, and we should find other, simpler solutions, attrs and listeners as well as attrs mentioned at the beginning of the article.
In brief, attrs is used to realize data transmission between grandparent and grandparent components, attrs realizes data transmission between grandparent and grandparent components, attrs realizes data transmission between grandparent and grandparent components, and Listeners realize event monitoring between grandparent and grandparent components. Let’s see how you can use these two features to communicate data between nested components across levels.
terms
Before understanding how attrs and Listeners and attrs and listeners accomplish component data communication, let’s take a quick look at what they are. The listeners are attrs and Listeners on the Vue website:
The interpretation of the $attrs
Contains feature bindings (except class and style) that are not recognized (and obtained) as props in the parent scope. When a component does not declare any props, this includes all parent scoped bindings (except class and style), and internal components can be passed in via v-bind=”$attrs” — useful when creating high-level components.
The interpretation of the $listeners
Contains v-ON event listeners in the parent scope (without the.native modifier). Internal components can be passed in via V-on =”$Listeners “– useful for creating higher-level components.
The official explanation is pretty clear. In fact, you can think of attrs as a set of attributes, attrs as a set of attributes, and listeners as a set of events, Both store data in the form of objects. To put it more simply, Attrs is used to transmit data between grandparent and grandparent components, attrs is used to transmit data between grandparent and grandparent components, attrs is used to transmit data between grandparent and grandparent components, attrs is used to transmit data between grandparent and grandparent components, and Listeners are used to monitor events between grandparent and grandparent components. Attrs inherits all parent component attributes (except the props, class, and style attributes) and is typically used on child elements of a child component. Attrs inherits all parent component attributes (except properties passed by props, class, and style) and is typically used on child elements of a child component. Attrs inherits all parent component attributes (except properties passed by props, class, and style) and is typically used on child elements of a child component. Listeners are an object that contains all listeners acting on the component, with the function v-ON pointing event listeners to a particular child element of the component (the child inherits events from the parent). To make it easier for you to understand these two properties, let’s go through some simple examples. Let’s start with a simple example:
<! -- ChildComponent.vue --><template>
<div class="child-component">
<h1>I am a {{professional}}</h1>
</div>
</template>
<script>
export default {
name: "ChildComponent".props: { professional: { type: String.default: "Spirit boy"}},created() {
console.log(this.$attrs, this.$listeners);
// Call the parent app.vue triggerTwo() method this.$Listeners. Two()}};</script>
Copy the code
<template>
<div id="app">
<ChildComponent :professional="professional"
:name="name"
@one.native="triggerOne"
@two="triggerTwo" />
</div>
</template>
<script>
import ChildComponent from "./components/ChildComponent.vue";
export default {
name: "app".data() {
return { professional: Happy Boy.name: "zhbb" };
},
components: { ChildComponent },
methods: {
triggerOne() {
console.log("one");
},
triggerTwo() {
console.log("two"); ,}}};</script>
Copy the code
App.vue (props); app.vue (props); app.vue (props); app.vue (props); app.vue (props); One event is the. Native modifier (which listens for the native event of the component root element). This simple example shows how attrs and attrs and attrs and listeners can pass data around, calling and processing where needed. For example, the parent app.vue triggerTwo() method is accessed by this.Component.two () in ChildComponent. Of course, we can also access the triggerTwo() method in parent app.vue via v−on=” Listeners.two(). Of course, we can also access the triggerTwo() method in the parent component app.vue via v-on=” Listeners.two(). There are also v−on=”listeners” on the process, regardless of the level of component nesting. We’ll talk more about this later. Also, in the example above, one of the properties is props, such as professional, and another is non-props, such as name. Components compile to treat non-props properties as raw properties and add them to DOM elements (HTML tags), such as name in the example above: If we want to remove the name attribute from the HTML tag so that it is not exposed, we can use the inheritAttrs attribute to do so.
InheritAttrs uses the default value true to apply all parent component attributes (except for props specific bindings) to the root element of the child component as a normal HTML feature. If you don’t want to use inheritAttrs as the root element of the component, the class attribute does. ** inheritAttrs: true inherits all attributes except props; InheritAttrs: false inherits only the class attribute **.
If we add inheritAttrs: false to the ChildComponent ChildComponent, the name (non-props) attribute in the recompiled code is no longer exposed:
Multi-level nested component data communication
We’ve spent a lot of time explaining attrs and attrs and attrs and listeners and how they communicate data within components. Returning to our example, see how attrs and attrs and Attrs and listeners communicate data between the three-level nested components mentioned at the beginning of this article.
<! -- ComponentA.vue --><template>
<div class="component-a">
<ComponentB :name="name"
:age="age"
@on-test1="onTest1"
@on-test2="onTest2" />
</div>
</template>
<script>
import ComponentB from "./ComponentB";
export default {
name: "ComponentA".components: { ComponentB },
data() {
return { name: "Big ZHBB".age: 23 };
},
methods: {
onTest1() {
console.log("test1 runing...");
},
onTest2() {
console.log("test2 running..."); ,}}};</script>
Copy the code
<! -- ComponentB.vue --><template>
<div class="component-b">
<h3>Props: {{age}}</h3>
<p>$attrs in component B: {{$attrs}}</p>
<p>$Listeners: {{$listeners}}</p>
<hr />
<ComponentC v-bind="$attrs"
v-on="$listeners" />
</div>
</template> <script>
import ComponentC from "./ComponentC";
export default {
name: "ComponentB".props: { age: { type: Number.default: 30}},inheritAttrs: false.components: { ComponentC },
mounted() {
this.$emit("test1");
console.log("ComponentB".this.$attrs, this.$listeners); }};</script>
Copy the code
<! -- ComponentC.vue --><template>
<div class="component-c">
<h3>Props set in component C: {{name}}</h3>
<p>$attrs in component C: {{$attrs}}</p>
<p>$Listeners: {{$listeners}}</p>
</div>
</template>
<script>
export default {
name: "ComponentC".props: { name: { type: String.default: "zhbb"}},inheritAttrs: false.mounted() {
this.$emit("test2");
console.log("ComponentC".this.$attrs, this.$listeners); }};</script>
Copy the code
<template>
<div id="app">
<ComponentA />
</div>
</template>
<script>
import ComponentA from "./components/ComponentA.vue";
export default {
name: "app".data() {},
components: {ComponentA },
methods: {}};</script>
Copy the code
Vue $once(‘hook:beforeDestroy’,e=>{}) using Vue how to destroy timer
1. Timer Hook optimization
Use hook automatic cleanup timer in Vue — programmatic event listener;
export default {
mounted() {
this.creatInterval('hello')
this.creatInterval('world')},methods: {creatInterval(msg) {
let timer = setInterval(() = > {
console.log(msg)
}, 1000)
this.$once('hook:beforeDestroy'.function() {
clearInterval(timer)
})
}
}
}
Copy the code
Vue projects use $.once(‘ hook:beforeDestory… ;
export default{
methods: {fun1(){
const timer = setInterval(() = >{
// What needs to be done
console.log(11111);
},1000);
this.$once('hook:beforeDestroy'.() = >{
clearInterval(timer);
timer = null; })}}}Copy the code
2. Timer Hook injection
Vue@hook those things;
<v-chart
@hook:mounted="loading = false"
@hook:beforeUpdated="loading = true"
@hook:updated="loading = false"
:data="data"
/>
Copy the code
Vue hook function hookEvent, listen to the component;
Perhaps try custom methods of hook child components or even change calls to data;
<custom-select @hook:updated="$_handleSelectUpdated" />
Copy the code
The updated hook function of the component is used to monitor data changes of a third-party component. The component does not provide the change event. After a look, Vue supports listening externally to the component’s lifecycle hook functions.
<template> <! Listen to the component's updated hook function --> <! All lifecycle hooks of a component can be listened for by @hook: hook function name.<custom-select @hook:updated="$_handleSelectUpdated" />
</template>
<script>
import CustomSelect from '.. /components/custom-select'
export default {
components: {
CustomSelect
},
methods: {
$_handleSelectUpdated() {
console.log('Custom-select component's updated hook function is fired')}}}</script>
Copy the code
In Vue, hooks are used as events, which are called hookEvents in the Vue source code.
$on(‘hook:updated’, () => {}) {$on(‘hook:updated’, () => {})