# VUE面試題
vue中MVVM的理解
M:模型(Model):數據模型;負責數據存儲。泛指后端進行的各種業務邏輯處理和數據操控,主要圍繞數據庫系統展開。
V就是:View 視圖: 負責頁面展示,也就是用戶界面。主要由 HTML 和 CSS 來構建
VM就是:視圖模型(View-Model): 負責業務邏輯處理(比如Ajax請求等),對數據進行加工后交給視圖展示
通過vue類創建的對象叫Vue實例化對象,這個對象就是MVVM模式中的VM層,模型通過它可以將數據綁定到頁面上,視圖可以通過它將數據映射到模型上
優點
1.低耦合。視圖(View)可以獨立于Model變化和修改,
2.可重用性。你可以把一些視圖邏輯放在一個ViewModel里面,讓很多view重用這段視圖邏輯
3.前后端分離,開發人員可以專注于業務邏輯(ViewModel)和數據的開發,設計人員可以專注于頁面設計
為什么說VUE是一個漸進式的javascript框架, 漸進式是什么意思?
VUE允許你將一個網頁分割成可復用的組件,每個組件都包含屬于自己的HTML、CSS、JAVASCRIPT以用來渲染網頁中相應的地方。對于VUE的使用可大可小,它都會有相應的方式來整合到你的項目中。所以說它是一個漸進式的框架。VUE是響應式的(reactive)這是VUE最獨特的特性,也就是說當我們的數據變更時,VUE會幫你更新所有網頁中用到它的地方。
vue生命周期
beforeCreate(創建前) :組件實例被創建之初,組件的屬性生效之前
//beforeCreate生命周期執行的時候,data和methods中的數據都還沒有初始化。不能在這個階段使用data中的數據和methods中的方法
created(創建后) :組件實例已經完全創建,屬性也綁定,但真實 dom 還沒有生成,$el 還不可用
// data 和 methods都已經被初始化好了,如果要調用 methods 中的方法,或者操作 data 中的數據,最早可以在這個階段中操作
beforeMount(掛載前) :在掛載開始之前被調用:相關的 render 函數首次被調用
//執行到這個鉤子的時候,在內存中已經編譯好了模板了,但是還沒有掛載到頁面中,此時,頁面還是舊的
mounted(掛載后) :在el 被新創建的 vm.$el 替換,并掛載到實例上去之后調用該鉤子
//到mounted周期的時候,Vue實例已經初始化完成了。此時組件脫離了創建階段,進入到了運行階段。 如果我們想要通過插件操作頁面上的DOM節點,最早可以在和這個階段中進行
beforeUpdate(更新前) :組件數據更新之前調用,真實DOM還沒被渲染
// 當執行這個鉤子時,頁面中的顯示的數據還是舊的,data中的數據是更新后的,頁面還沒有和最新的數據保持同步
update(更新后) :組件數據更新之后
//頁面顯示的數據和data中的數據已經保持同步了,都是最新的
activated(激活前) :keep-alive專屬,組件被激活時調用
//當組件被切回來時,再去緩存里找這個組件、觸發 activated鉤子函數。
deactivated(激活后) :keep-alive專屬,組件被銷毀時調用
//當組件被換掉時,會被緩存到內存中、觸發 deactivated 生命周期
beforeDestory(銷毀前) :組件銷毀前調用
//Vue實例從運行階段進入到了銷毀階段,這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于可用狀態。還沒有真正被銷毀
destoryed(銷毀后) :組件銷毀前調用
//這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于不可用狀態。組件已經被銷毀了。
Vue 實例從創建到銷毀的過程,就是生命周期。從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、銷毀等一系列過程,稱之為 Vue 的生命周期。
Vue子組件和父組件執行順序
加載渲染過程:beforeCreate(父) —> created(父)—>beforeMount(父)—>beforeCreate(子)—>created(子)—>beforeMount(子)—>mounted(子)—>mounted(父)
更新過程:beforeUpdate(父) —> beforeUpdate(子) —> update(子) —> update(父)
銷毀過程:beforeDestory(父) —> beforeDestory(子) —> destoryed(子) —> destoryed(父)
v-el 作用是什么
提供一個在頁面上已存在的 DOM 元素作為 Vue 實例的掛載目標。可以是 CSS 選擇器,也可以是一個 HTMLElement 實例。
1
Vue的el屬性和$mount優先級?
new Vue({
router,
store,
el: '#app',
render: h => h(App)
}).$mount('#div')
/*當出現上面的情況就需要對el和$mount優先級進行判斷,從下面的官方圖片我們可以看出來,
el的優先級是高于$mount的,因此以el掛載節點為準*/
Vue實現數據雙向綁定的原理:Object.defineProperty()
vue實現數據雙向綁定主要是:采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應監聽回調。
vue的數據雙向綁定 將MVVM作為數據綁定的入口,整合Observer,Compile和Watcher三者,通過Observer來監聽自己的model的數據變化,通過Compile來解析編譯模板指令(vue中是用來解析 {undefined{}}),最終利用watcher搭起observer和Compile之間的通信橋梁,達到數據變化 —>視圖更新;視圖交互變化(input)—>數據model變更雙向綁定效果。
數據雙向綁定示例:
<body>
<div id="app">
<input type="text" id="txt">
<p id="show"></p>
</div>
</body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
</script>
假如data里面的數據不想做響應式,該怎么做
1、數據放在vue實例外(vue template中訪問不到數據)
2、created, mounted鉤子函數中定義(注意data中不要聲明該變量名)
3、自定義Options
4、Object.freeze()
如何將獲取data中某一個數據的初始狀態?
data() {
return {
num: 10
},
mounted() {
this.num = 1000
},
methods: {
countNum() {
// 可以通過this.$options.data().keyname來獲取初始值
// 計算出num增加了多少
console.log(1000 - this.$options.data().num)
}
}
動態指令設置及動態傳參
<template>
...
<child @[someEvent]="handleSomeEvent()" :[someProps]="1000" />...
</template>
<script>
...
data(){
return{
...
someEvent: type ? "click" : "dbclick",
someProps: type ? "num" : "price"
}
},
methods: {
handleSomeEvent(){
// do some
}
}
</script>
//應用場景:用于頁面中根據不同的返回值進行事件的觸發和值的傳參
Vue組件間的參數傳遞
1.父組件傳給子組件:子組件通過props方法接受數據;
2.子組件傳給父組件:$emit方法傳遞參數
3.非父子組件間的數據傳遞,兄弟組件傳值借用eventBus,就是創建一個事件中心,相當于中轉站,可以用它來傳遞事件和接收事件。發送數據使用 $emi t方法,使用 $on 接收
更多詳細內容可以查看我的另一篇文章Vue父子組件間傳值方法集
provide和inject使用(響應式)
provide和inject是用來實現父組件向深層的子組件傳值和接收的語法,具體如下:
// 祖先組件
provide(){
return {
// keyName: { name: this.name }, // value 是對象才能實現響應式,也就是引用類型
keyName: this.changeValue // 通過函數的方式也可以[注意,這里是把函數作為value,而不是this.changeValue()]
// keyName: 'test' value 如果是基本類型,就無法實現響應式
}
},
data(){
return {
msg:'初始mesg'
}
},
methods: {
changeValue(){
this.msg= '改變后的msg'
}
}
// 后代組件
inject:['keyName']
create(){
console.log(this.keyName) // 改變后的msg
}
詳情參考我的這篇文章
provide / Inject淺析
Vue的路由實現:hash模式 和 history模式
hash模式: 在瀏覽器中符號“#”,#以及#后面的字符稱之為hash,用window.location.hash讀取;
特點:hash雖然在URL中,但不被包括在HTTP請求中;用來指導瀏覽器動作,對服務端安全無用,hash不會重加載頁面。
history模式: history 模式下,前端的 URL 必須和實際向后端發起請求的 URL 一致,history采用HTML5的新特性;且提供了兩個新方法:pushState(),replaceState()可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監聽到狀態變更。
$nextTick原理及運用
1.nextTick是啥?
Vue.nextTick( [callback, context] ):在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM。
1
2.為什么需要它呢?
Vue是異步執行dom更新的,一旦觀察到數據變化,Vue就會開啟一個隊列,然后把在同一個事件循環 (event loop)
當中觀察到數據變化的 watcher 推送進這個隊列。如果這個watcher被觸發多次,只會被推送到隊列一次。
這種緩沖行為可以有效的去掉重復數據造成的不必要的計算和DOm操作。而在下一個事件循環時,Vue會清空隊列,并進行必要的DOM更新。
假使你設置 vm.someData = 'new value',DOM 并不會馬上更新,而是在異步隊列被清除,也就是下一個事件循環
開始時執行更新時才會進行必要的DOM更新。如果此時你想要根據更新的 DOM 狀態去做某些事情,就會出現問題。
為了在數據變化之后等待 Vue 完成更新 DOM ,可以在數據變化之后立即使用 Vue.nextTick(callback) 。
這樣回調函數在 DOM 更新完成后就會調用。
3我再什么地方用它呢?
1、在Vue生命周期的created()鉤子函數進行的DOM操作一定要放在Vue.nextTick()的回調函數中。
原因是在created()鉤子函數執行的時候DOM 其實并未進行任何渲染,而此時進行DOM操作無異于徒勞,
所以此處一定要將DOM操作的js代碼放進Vue.nextTick()的回調函數中。與之對應的就是mounted鉤子函數,
因為該鉤子函數執行時所有的DOM掛載和渲染都已完成,此時在該鉤子函數中進行任何DOM操作都不會有問題 。
2、在數據變化后要執行的某個操作,而這個操作需要使用隨數據改變而改變的DOM結構的時候
(譬如v-if/v-show根據字段變化顯隱),這個操作都應該放進Vue.nextTick()的回調函數中。
Compute和watch區別和應用場景
computed
//計算屬性中的屬性不需要在data中定義,而且必須有return
data(){
return{
firstname:"張",
lastname:"三"
}
}
computehd(){
fullname(){
return this.firstname+this.lastname
}
}
/*計算屬性具有緩存,計算屬性是基于它們的依賴進行緩存的,只有在它的相關依賴發生改變時才會重新求值。
只要計算屬性的依賴沒有改變,那么調用它就會直接返回之前的緩存。 同時computed對于其中變量的依賴時多個
的時候,只要其中一個發生了變化都會觸發這個函數*/
//應用場景:當一個變量的值受多個變量的值影響
watch
//監聽器watch中的值需要在data中定義,且函數有參數,newval和oldval
data: {
firstName: '張',
lastName: '三',
fullName: '張三r'
},
watch: {
firstName: function (oval,nval) {
this.fullName = nval + ' ' + this.lastName
},
lastName: function (oval,nval) {
this.fullName = this.firstName + ' ' + nval
},
immediate: true,// 代表在wacth里聲明了firstName之后立即先去執行其函數方法
deep: true //深度監聽
}
//watch的依賴是單個的,它每次只可以對一個變量進行監控,并且區別于computed屬性,監聽器watch可以是異步的而computed則不行
//應用場景:當一個變量的值影響著多個變量的值
filters
//過濾器分為全局過濾和局部過濾,當命名沖突時以局部過濾器權重高
//插值中
{{msg|filterMsg}}
//bind中
<div v-bind:"id|filterId"></div>
//運用場景:
//一般來說我們用過濾器來格式化一些數據或者渲染的文本對于格式展現的要求
全局:
Vue.filter('過濾器名',function(value){
//do some
})
局部:
filters:{
過濾器名稱:function(value){
//do some
}
}
vuex
vuex是什么?怎么使用?哪種功能場景使用它?
//是什么
vue框架中狀態管理。在main.js引入store注入。新建一個目錄store 。場景有:單頁應用中,組件之間的狀態,
音樂播放、登錄狀態、加入購物車等。
//屬性:
State、 Getter、Mutation 、Action、 Module
//State
state是數據源存放地,對應于一般Vue對象里面的data。state里面存放的數據是響應式的,
Vue組件從store中讀取數據,若是store中的數據發生改變,依賴這個數據的組件也會發生更新
需要通過mapState把全局 state 和 getters 映射到當前組件的 computed 計算屬性中。
//Getter
getters 可以對State進行計算操作,在多個組件間復用
//Mutation 、Action
Action 類似于 mutation,不同在于Action 提交的是 mutation,而不是直接變更狀態;Action 可以包含任意異步操作。
//Module
Vuex允許我們將store分隔成模塊(module),每個模塊擁有自己的state,mutation,action,getter,甚至是嵌套子模塊
//使用場景
一句話,不要為了使用vuex而去使用vuex,推薦組件間數據復用,記錄登錄及其它狀態值數據,一些需要緩存的數據使用vuex都能達到很好的管理
v-show 與 v-if 的區別,兩者的優先級
v-show指令是通過修改元素的display的CSS屬性讓其顯示或者隱藏;
v-if指令是直接銷毀和重建DOM達到讓元素顯示和隱藏的效果;
使用v-show會更加節省性能上的開銷;當只需要一次顯示或隱藏時,使用v-if更加合理。
//優先級
v-for優先級比v-if高
//注意事項
不要把 v-if 和 v-for 同時用在同一個元素上,帶來性能方面的浪費(每次渲染都會先循環再進行條件判斷)
正確的做法應該是再v-for的外面新增一個模板標簽template,在template上使用v-if也能結合filters或者是computed屬性對數據進行加工,避免v-if判斷,更好的渲染
vue路由傳參
//通過 params 傳參
this.$router.push({
name: '目標組件名',
params: {
id: id
}
})
//接收:
this.$route.params
//通過 query 傳參
this.$router.push({
path: '目標組件路徑',
query: {
id: id
}
})
//接收
this.$route.query
//區別:query使用path來引入,params使用name來引入,接收方式是this.$route.query.name和this.$route.params.name,值得注意的是query傳遞的參數會顯示在url后面以?id=?形式展示。
//動態路由傳參
//直接調用$router.push 實現攜帶參數的跳轉
this.$router.push({
path: `/particulars/${id}`,
})
//通過this.$route.params.id接收,可以看到,和上面傳參不一樣的是我們直接把動態參數加在路徑后面實現動態路由
vue路由的鉤子函數
導航鉤子種類
全局導航鉤子、組件內鉤子、單獨路由獨享組件
//路由的鉤子函數總結有6個
全局的路由鉤子函數:beforeEach、afterEach
單個的路由鉤子函數:beforeEnter
組件內的路由鉤子函數:beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate
全局導航鉤子
全局前置守衛:beforeEach
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法不然會阻塞路由。執行效果依賴 next 方法的調用參數。
next()方法接收的參數:
全局后置鉤子:afterEach
router.afterEach((to, from) => {
// do someting
});
//后置鉤子并沒有 next 函數
路由獨享的鉤子
路由獨享的導航鉤子,它是在路由配置上直接進行定義的,參數的使用,和全局前置守衛是一樣的
使用的鉤子函數與全局路由守衛一致,為beforeEnter,不同的是,路由獨享守衛是定義在路由記錄中,全局路由守衛是定義在入口文件中,路由獨享守衛只在路由進入時有效,全局路由守衛是所有路由跳轉都會被攔截。
組件內的導航鉤子
beforeRouteEnter:在渲染該組件的對應路由前調用
beforeRouteUpdate:在當前路由改變,但是該組件被復用時調用
beforeRouteLeave:導航離開該組件的對應路由時調用
//注意:beforeRouteEnter 不能獲取組件實例 this,因為當守衛執行前,組件實例被沒有被創建出來,剩下兩個鉤子則可以正常獲取組件實例 this
共享組件將不會重新渲染問題
我們有時候開發中會把多個路由解析為同一個Vue組件。問題是,Vue默認情況下共享組件將不會重新渲染,如果你嘗試在使用相同組件的路由之間進行切換,則不會發生任何變化,此時我們需要傳遞key來區分,達到刷新的目的
const routes = [
{
path: "/a",
component: MyComponent
},
{
path: "/b",
component: MyComponent
},
];
<template>
<router-view :key="$route.path"></router-view>
</template>
插槽
插槽就是子組件中用slot標簽定義的預留位置,有name屬性叫具名插槽,不設置name屬性的叫不具名插槽,使用插槽主要是為了在父組件中使用子組件標簽的時候可以往子組件內寫入html代碼。
插槽使用:
//父組件:
<template>
<div>
<div>這是父組件</div>
<son>slot內容</son>
</div>
</template>
//子組件
<template>
<div>
<div>這是子組件</div>
<input type="text" placeholder="請輸入">
</div>
</template>
//一般情款下想在子組件內插入內容像上面直接在標簽里書寫時不顯示的需要以slot為媒介
//改寫后:
//子組件:
<template>
<div>
<div>這是子組件</div>
<input type="text" placeholder="請輸入">
<slot></slot>
</div>
</template>
//此時我們沒有給插槽設置name,所以這是一個不具名插槽
//具名插槽:
//父組件:
<template>
<div>
<div>這是父組件</div>
<son>
<template slot="myslot">
<div>
實踐具名slot
</div>
</template>
</son>
</div>
</template>
//子組件
<template>
<div>
<div>這是子組件</div>
<input type="text" placeholder="請輸入">
<slot name="myslot"></slot>
</div>
</template>
//此時設置name屬性的插槽為具名插槽,與之相對應的用了slot的設置為相同屬性名的內容則會被渲染在插槽中,此時如果有未設置slot插槽名的內容則會被渲染在不具名插槽中
插槽作用域:
//父組件:
<template>
<div>
<div>父組件</div>
<son>
<template slot="myslot" slot-scope="props">
<ul>
<li v-for="item in props.data">
{{item}}
</li>
</ul>
</template>
</son>
</div>
</template>
//子組件:
<template>
<div>
<div>子組件</div>
<input type="text" placeholder="請輸入">
<slot name="myslot" :data='list'></slot>
</div>
</template>
<script>
export default {
name:'Son',
data(){
return{
list:[
{name:"張三",age:3},
{name:"李四",age:4},
{name:"王五",age:5}
]
}
}
}
</script>
mixins
mixins是一種分發Vue組件中可復用功能的一種靈活方式。混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被混入該組件本身的選項。
mixins是一個JavaScript對象,可以包含組件中的任意選項,比如Vue實例中生命周期的各個鉤子函數,也可以是data、components、methods或directives等
運用:
//mixin文件
export const myMixin={
data(){
return{
msg:1
}
},
created(){
console.log('myMixin')
},
methods:{
Fn(){
console.log('myMixin')
}
}
}
//引入
<template>
<div>運用mixin的組件</div>
</template>
<script>
import {myMixin} from'目標文件路徑'
export default{
mixins:[myMixin]
}
</script>
特點:
1、在組件A對混入的數據做出更改后組件B獲取到的仍是混入初始設置的數據,組件間操作互不污染。
2、值為對象的如methods,components等,選項會被合并,組件會覆蓋混入對象的方法。
比如混入對象里有個方法A,組件里也有方法A,這時候在組件里調用的話,執行的是組件里的A方法。
3、created,mounted等,就會被合并調用,混合對象里的鉤子函數在組件里的鉤子函數之前調用,
同一個鉤子函數里,會先執行混入對象的東西,再執行本組件的。
4、在mixins里面包含異步請求函數的時候,通過直接調用異步函數獲取返回數據
運用場景區別:
vuex:用來做狀態管理,可以看做全局變量,里面定義的變量在每個組件中均可以使用和修改,
在任一組件中修改此變量的值之后,其他組件中此變量的值也會隨之修改。
mixins:可以定義共用的變量,在每個組件中使用,引入組件中之后,各個變量是相互獨立的,
值的修改在組件中不會相互影響。
父子組件:父子組件相對來說比較獨立,只是父組件將一部分使用子組件,而mixins更像是對于組件的拓展,并且
組件可以對于混入的數據和方法進行多樣化操作。
vue自定義組件添加事件
使用修飾符.native 監聽組件根元素的原生事件
<my-button @click.native="alert()" names="點擊觸發"></my-button>
axios
//axios特點:
在瀏覽器中創建XMLHttpRequest請求
在node.js中發送http請求
支持Promise API
攔截請求和響應
轉換請求和響應數據
取消要求
自動轉換JSON數據
客戶端支持防止CSRF/XSRF(跨域請求偽造)
//axios的請求方式:
axios(config)
axios.request(config)
axios.get(url [,config])
axios.post(url [,data [,config]])
axios.put(url [,data [,config]])
axios.delete(url [,config])
axios.patch(url [,data [,config]])
axios.head(url [,config])
axios一般用法配置與請求
//引入axios
import axios from 'axios'
//定義axios請求接口的baseURL
axios.default.baseURL = 'http://localhost:8080/api/products'
//執行GET請求
axios.get('/user?ID=12345') //返回的是一個Promise
.then(res=>console.log(res))
.catch(err=>console.log(err));
//可配置參數的方式
axios.get('/user',{
params:{
ID:12345
}
}).then(res=>console.log(res))
.catch(err=>console.log(err));
//發送post請求
axios.post('/user',{
firstName: 'simon',
lastName:'li'
}).then(res=>console.log(res))
.catch(err=>console.log(err));
//發送post請求
axios({
method: 'post', //請求方式,默認是get請求
url:'/user/12345', //地址
data:{ //參數
firstName: 'simon',
lastName: 'li'
}
});
發送并發請求:
//發送多個請求(并發請求),類似于promise.all,若一個請求出錯,那就會停止請求
const get1 = axios.get('/user/12345');
const get2 = axios.get('/user/12345/permission');
axios.all([get1,get2])
.then(axios.spread((res1,res2)=>{
console.log(res1,res2);
}))
.catch(err=>console.log(err))
//函數返回的是一個數組axios.spread(callback)可用于將結果數組展開
請求配置:
{
//服務器的地址,是必須的選項
url: '/user',
//請求的方式,若沒有則默認是get
method:'get',
//如果url不是絕對地址,則會加上baseURL
baseURL: 'http://localhost:3000/',
//transformRequest允許請求的數據在發送至服務器之前進行處理,這個屬性只適用于put、post、patch方式
//數組的最后一個函數必須返回一個字符串或者一個'ArrayBuffer'或'Stream'或'Buffer' 實例或'ArrayBuffer','Formdata',
//若函數中用到了headers,則需要設置headers屬性
transformRequest: [function(data,headers){
//根據需求對數據進行處理
return data;
}],
//transformResponse允許對返回的數據傳入then/catch之前進行處理
transformResponse:[function(data){
//依需要對數據進行處理
return data;
}],
//headers是自定義的要被發送的信息頭
headers: {'X-Requested-with':'XMLHttpRequest'},
//params是請求連接中的請求參數,必須是一個純對象
params:{
ID:12345
},
//paramsSerializer用于序列化參數
paramsSerializer: function(params){
return Qs.stringify(params,{arrayFormat:'brackets'});
},
//data是請求時作為請求體的數據——request.body
//只適用于put、post、patch請求方法
//瀏覽器:FormData,File,Blob;Node:stream
data:{
firstName: 'simon',
},
//timeout定義請求的時間,單位是毫秒,如果請求時間超過設定時間,請求將停止
timeout:1000,
//withCredentials表明跨跨域請求書否需要證明。
withCredentials:false, //默認值
//adapter適配器,允許自定義處理請求
//返回一個promise
adapter:function(config){
/*...*/
},
//auth表明HTTP基礎的認證應該被使用,并提供證書
auth:{
username:'simon',
password:'123456',
},
//responseType表明服務器返回的數據類型,這些類型包括:json/blob/document/ arraybuffer/text/stream
responseType: 'json',
//proxy定義服務器的主機名和端口號
//auth屬性表明HTTP基本認證應該跟proxy相連接,并提供證書
//這將設置一個'Proxy-Authorization'頭(header),覆蓋原來自定義的
proxy:{
host:127.0.0.1,
port:8080,
auth:{
username:'simon',
password:'123456'
}
},
//取消請求
cancelToken: new CancelToken(cancel=>{})
}
ajax
詳情可以查看我之前寫過的ajax封裝文章,詳細了說明封裝過程ajax優劣分析及封裝
- 常見面試題
- 一.Java常見面試題
- 1.Java基礎
- 3.面向對象概念
- 10.Java面試題
- Java基礎知識面試題(總結最全面的面試題)
- 設計模式面試題(總結最全面的面試題)
- Java集合面試題(總結最全面的面試題)
- JavaIO、BIO、NIO、AIO、Netty面試題(總結最全面的面試題)
- Java并發編程面試題(總結最全面的面試題)
- Java異常面試題(總結最全面的面試題)
- Java虛擬機(JVM)面試題(總結最全面的面試題)
- Spring面試題(總結最全面的面試題)
- Spring MVC面試題(總結最全面的面試題)
- Spring Boot面試題(總結最全面的面試題)
- Spring Cloud面試題(總結最全面的面試題)
- Redis面試題(總結最全面的面試題)
- MyBatis面試題(總結最全面的面試題)
- TCP、UDP、Socket、HTTP面試題(總結最全面的面試題)
- 二、MySQL面試題
- 1.基礎部分
- MySQL面試題(總結最全面的面試題)
- HBase相關面試題整理
- Nginx面試題(總結最全面的面試題)
- RabbitMQ面試題(總結最全面的面試題)
- Dubbo面試題(總結最全面的面試題)
- ZooKeeper面試題(總結最全面的面試題)
- Tomcat面試題(總結最全面的面試題)
- Linux面試題(總結最全面的面試題)
- 超詳細的Django面試題
- SSM面試題
- 15個高頻微信小程序面試題
- VUE面試題
- Python面試題
- 二、常見問題解答列表
- 1.查看端口及殺死進程
- 三、學習電子書