vue面試題
一、vue優點
1.輕量級框架:只關注視圖層,是一個構建數據的視圖集合,大小只有幾十kb;
2.簡單易學:國人開發,中文文檔,不存在語言障礙 ,易于理解和學習;
3.雙向數據綁定:保留了angular的特點,在數據操作方面更為簡單;
4.組件化:保留了react的優點,實現了html的封裝和重用,在構建單頁面應用方面有著獨特的優勢;視圖,數據,結構分離:使數據的更改更為簡單,不需要進行邏輯代碼的修改,只需要操作數據就能完成相關操作;
5.虛擬DOM:dom操作是非常耗費性能的, 不再使用原生的dom操作節點,極大解放dom操作,但具體操作的還是dom不過是換了另一種方式;
6.運行速度更快:相比較與react而言,同樣是操作虛擬dom,就性能而言,vue存在很大的優勢。
二、vue中的父子組件之間的數據傳遞之props、$ref和$emit
props是用于數據之間的傳遞(父組件向子組件),ref也可以用于數據之間的傳遞(ref用在子組件上,指向的是組件實例,可以理解為對子組件的索引,通過ref可能獲取到在子組件里定義的屬性和方法。),$emit是用于事件之間的傳遞(子組件觸發父組件里面的方法)。
1.props是用于父組件向子組件傳遞數據信息(所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外變更父級組件的狀態,從而導致你的應用的數據流向難以理解。每次父級組件發生變更時,子組件中所有的 prop 都將會刷新為最新的值。這意味著你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制臺中發出警告。)
這里有兩種常見的試圖變更一個 prop 的情形:
A.這個 prop 用來傳遞一個初始值;這個子組件接下來希望將其作為一個本地的 prop 數據來使用。在這種情況下,最好定義一個本地的 data property 并將這個 prop 用作其初始值:
props: ['initialCounter'],
data:function(){return{counter:this.initialCounter? }}
B.這個 prop 以一種原始的值傳入且需要進行轉換。在這種情況下,最好使用這個 prop 的值來定義一個計算屬性:
props: ['size'],
computed: {normalizedSize:function(){returnthis.size.trim().toLowerCase()? }}
注意在 JavaScript 中對象和數組是通過引用傳入的,所以對于一個數組或對象類型的 prop 來說,在子組件中改變變更這個對象或數組本身將會影響到父組件的狀態。
2.通過ref 實現通信
對于ref官方的解釋是:ref 是被用來給元素或子組件注冊引用信息的。引用信息將會注冊在父組件的 refs 對象上。
那應該怎么理解?看看下面的解釋:
(1).如果ref用在子組件上,指向的是組件實例,可以理解為對子組件的索引,通過ref可能獲取到在子組件里定義的屬性和方法。
(2).如果ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通過$ref可能獲取到該DOM 的屬性集合,輕松訪問到DOM元素,作用與JQ選擇器類似。
prop和$ref之間的區別:
1.prop 著重于數據的傳遞,它并不能調用子組件里的屬性和方法。像創建文章組件時,自定義標題和內容這樣的使用場景,最適合使用prop。
2.ref 著重于索引,主要用來調用子組件里的屬性和方法,其實并不擅長數據傳遞。而且ref用在dom元素的時候,能使到選擇器的作用,這個功能比作為索引更常有用到。
3.通過emit 實現通信
上面兩種示例主要都是父組件向子組件通信,而通過emit實現子組件向父組件通信。對于emit實現子組件向父組件通信。
vm.$emit( event, […arg] )? $emit是可以傳遞多個參數的
$emit 綁定一個自定義事件event,當這個這個語句被執行到的時候,就會將參數arg傳遞給父組件,父組件通過@event監聽并接收參數。
三、v-show和v-if指令的共同點和不同點?
共同點:都能控制元素的顯示和隱藏;
不同點:實現本質方法不同,v-show本質就是通過控制css中的display設置為none,控制隱藏,只會編譯一次;v-if是動態的向DOM樹內添加或者刪除DOM元素,若初始值為false,就不會編譯了。而且v-if不停的銷毀和創建比較消耗性能。
總結:如果要頻繁切換某節點,使用v-show(切換開銷比較小,初始開銷較大)。如果不需要頻繁切換某節點使用v-if(初始渲染開銷較小,切換開銷比較大)。
四、如何讓CSS只在當前組件中起作用?
在組件中的style前面加上scoped
五、<keep-alive></keep-alive>
1.keep-alive簡介:keep-alive是 Vue 內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。
用法也很簡單:
<keep-alive>
? <component>
? ? <!-- 該組件將被緩存! -->
? </component>
</keep-alive>
2.props
include - 字符串或正則表達,只有匹配的組件會被緩存
// 組件 a
export default {
? name: 'a',
? data () {
? ? return {}
? }
}
<keep-alive include="a">//可以保留它的狀態或避免重新渲染
? <component>
? ? <!-- name 為 a 的組件將被緩存! -->
? </component>
</keep-alive>//可以保留它的狀態或避免重新渲染
exclude - 字符串或正則表達式,任何匹配的組件都不會被緩存
<keep-alive exclude="a">
? <component>
? ? <!-- 除了 name 為 a 的組件都將被緩存! -->
? </component>
</keep-alive>//可以保留它的狀態或避免重新渲染
問題:如果只想router-view里面某個組件被緩存,怎么辦?
1.使用 include/exclude
2.增加 router.meta 屬性
// 組件 a
export default{name:'a',data(){return{}}}
缺點:需要知道組件的 name,項目復雜的時候不是很好的選擇
優點:不需要例舉出需要被緩存組件名稱
增加 router.meta 屬性
// routes 配置
export default [{path:'/:id',name:'edit',component:Edit,meta:{keepAlive:false// 不需要被緩存}}]
? {
? ? path: '/',
? ? name: 'home',
? ? component: Home,
? ? meta: {
? ? ? keepAlive: true // 需要被緩存
? ? }
? }, {
? ? path: '/:id',
? ? name: 'edit',
? ? component: Edit,
? ? meta: {
? ? ? keepAlive: false // 不需要被緩存
? ? }
? }
]
<keep-alive>
? ? <router-view v-if="$route.meta.keepAlive">
? ? ? ? <!-- 這里是會被緩存的視圖組件,比如 Home! -->
? ? </router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
? ? <!-- 這里是不被緩存的視圖組件,比如 Edit! -->
</router-view>
vue實現前進刷新,后退不刷新:https://juejin.im/post/5a69894a518825733b0f12f2
參考文章:http://www.lxweimin.com/p/0b0222954483
六、如何獲取dom?
答:ref="domName" 用法:this.$refs.domName
七、說出幾種vue當中的指令和它的用法?
v-model雙向數據綁定;
v-for循環;
v-if v-show 顯示與隱藏;
v-on事件;v-once: 只綁定一次。
八、vue-loader是什么?使用它的用途有哪些?
Vue Loader 是一個webpack的 loader,它允許你以一種名為單文件組件 (SFCs)的格式撰寫 Vue 組件
Vue Loader 還提供了很多酷炫的特性:
1.允許為 Vue 組件的每個部分使用其它的 webpack loader,例如在<style>的部分使用 Sass 和在<template>的部分使用 Pug;
2.允許在一個.vue文件中使用自定義塊,并對其運用自定義的 loader 鏈;
3.使用 webpack loader 將<style>和<template>中引用的資源當作模塊依賴來處理;
4.為每個組件模擬出 scoped CSS;
5.在開發過程中使用熱重載來保持狀態。
用途:js可以寫es6、style樣式可以scss或less、template可以加jade等
九、v-for 為什么使用key?
需要使用key來給每個節點做一個唯一標識,Diff算法就可以正確的識別此節點。作用主要是為了高效的更新虛擬DOM。
十、axios
1.axios 簡介
axios 是一個基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特征:
1.從瀏覽器中創建 XMLHttpRequest
2.從 node.js 發出 http 請求
3.支持 Promise API
4.攔截請求和響應
5.轉換請求和響應數據
6.取消請求
7.自動轉換JSON數據
8.客戶端支持防止 CSRF/XSRF
axios中的發送字段的參數是data跟params兩個,兩者的區別在于params是跟請求地址一起發送的,data的作為一個請求體進行發送,params一般適用于get請求,data一般適用于post put 請求。
安裝
npm安裝 $ npm install axios --save
通過cdn引入 <scriptsrc="https://unpkg.com/axios/dist/axios.min.js"></script>
發送GET請求
// created:vue生命周期中的鉤子函數,在這個時間點,data中的數據已經注入到響應式系統中
created(){
? ? axios.get('api/getData.php',{? ? ?? // 還可以直接把參數拼接在url后邊
? ? ? ? params:{
? ? ? ? ? ? title:'眼鏡'
? ? ? ? }
? ? }).then(function(res){
? ? ? ? this.goodsList = res.data;
? ? }).catch(function (error) {
? ? ? ? console.log(error);
? ? });
}
發送POST請求
axios.post('/user', {
? ? firstName: 'Fred',
? ? lastName: 'Flintstone'
}).then(function (response) {
? ? console.log(response);
}).catch(function (error) {
? ? console.log(error);
});
執行多個并發請求
//獲得用戶信息的請求
function getUserAccount() {
? ?? return axios.get('/user/12345');
}
//獲取用戶許可證的請求
function getUserPermissions() {
? ?? return axios.get('/user/12345/permissions');
}
axios.all( [ getUserAccount(),? getUserPermissions() ] )
? ? .then(axios.spread(function (acct, perms) {
? ? ? ? //兩個請求現已完成
? ? })
);
請求攔截器和響應攔截器
//請求攔截器
axios.interceptors.request.use(
? function (config) {
? ? ? // 在發送請求之前做些什么
? ? ? return config;
? },
? function (error) {
? ? ? // 對請求錯誤做些什么
? ? ? return Promise.reject(error);
? }
);
//響應攔截器
axios.interceptors.response.use(
? function (config) {
? ? ? // 對響應數據做點什么
? ? ? return config;
? },
? function (error) {
? ? ? // 對響應錯誤做點什么
? ? ? return Promise.reject(error);
? }
);
Vue中axios在發送POST請求時,參數的處理
1. 下載安裝第三方模塊 qs ->? npm install qs --save-dev
2. 處理方式
// 第一種: 直接在發送的時候,對數據進行qs.stringify處理
// 缺點: 如果項目大,有大量的請求需要發送,那么一個一個加會很麻煩
axios.post("/checkLogin.php", qs.stringify({
? name, pwd
}));
// 第二種: 使用axios.create創建一個新的axios實例,統一對數據進行處理, 同時也要借助qs模塊
const Axios = axios.create({
? baseURL: '/api',
? transformRequest: [function (data) {
? ? const d = qs.stringify(data)
? ? return d;
? }]
})
Axios.post("/checkLogin.php", {
? name, pwd
});
十一、v-modal的使用
v-model用于表單數據的雙向綁定,其實它就是一個語法糖,這個背后就做了兩個操作:
1.v-bind綁定一個value屬性;
2.v-on指令給當前元素綁定input事件。
十二、請說出vue.cli項目中src目錄每個文件夾和文件的用法?
assets文件夾是放靜態資源;components是放組件;router是定義路由相關的配置; app.vue是一個應用主組件;main.js是入口文件。
十三、分別簡述computed和watch的區別和使用場景
1.區別
watch中的函數是不需要調用的
computed內部的函數調用的時候不需要加()
watch??屬性監聽 監聽屬性的變化
computed:計算屬性通過屬性計算而得來的屬性
watch需要在數據變化時執行異步或開銷較大的操作時使用
對于任何復雜邏輯或一個數據屬性在它所依賴的屬性發生變化時,也要發生變化,這種情況下,我們最好使用計算屬性computed。
computed 屬性的結果會被緩存,除非依賴的響應式屬性變化才會重新計算。主要當作屬性來使用;
computed中的函數必須用return返回最終的結果
當computed中的函數所依賴的屬性如果沒有發生改變的時候,那么調用當前函數的時候結果會從緩存中讀取
watch 一個對象,鍵是需要觀察的表達式,值是對應回調函數。主要用來監聽某些特定數據的變化,從而進行某些具體的業務邏輯操作;
2.使用場景
computed:當一個屬性受多個屬性影響的時候就需要用到computed
例子: 購物車商品結算的時候
watch:當一條數據影響多條數據的時候就需要用watch
例子:搜索數據
十四、v-on可以監聽多個方法嗎?
可以,栗子:<input? type="text"? v-on="{ input:onInput,focus:onFocus,blur:onBlur, }">。
十五、$nextTick的使用
當你修改了data的值然后馬上獲取這個dom元素的值,是不能獲取到更新后的值,你需要使用$nextTick這個回調,讓修改后的data值渲染更新到dom元素之后在獲取,才能成功。
在下次 DOM 更新循環結束之后執行延遲回調。nextTick主要使用了宏任務和微任務。根據執行環境分別嘗試采用
Promise
MutationObserver
setImmediate
如果以上都不行則采用setTimeout
定義了一個異步方法,多次調用nextTick會將方法存入隊列中,通過這個異步方法清空當前隊列。
十六、vue組件中data為什么必須是一個函數?
因為JavaScript的特性所導致,在component中,data必須以函數的形式存在,不可以是對象。組件中的data寫成一個函數,數據以函數返回值的形式定義,這樣每次復用組件的時候,都會返回一份新的data,相當于每個組件實例都有自己私有的數據空間,它們只負責各自維護的數據,不會造成混亂。而單純的寫成對象形式,就是所有的組件實例共用了一個data,這樣改一個全都改了。
十七、漸進式框架的理解
主張最少;可以根據不同的需求選擇不同的層級;
十八、Vue中雙向數據綁定是如何實現的?
vue.js 是采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應的監聽回調。
詳細請參考:? http://www.cnblogs.com/libin-1/p/6893712.html
具體步驟:
第一步:需要observe的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上setter和getter
這樣的話,給這個對象的某個值賦值,就會觸發setter,那么就能監聽到了數據變化
第二步:compile解析模板指令,將模板中的變量替換成數據,然后初始化渲染頁面視圖,并將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變動,收到通知,更新視圖
第三步:Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是:
1、在自身實例化時往屬性訂閱器(dep)里面添加自己
2、自身必須有一個update()方法
3、待屬性變動dep.notice()通知時,能調用自身的update()方法,并觸發Compile中綁定的回調,則功成身退。
第四步:MVVM作為數據綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變更的雙向綁定效果。
核心:關于VUE雙向數據綁定,其核心是 Object.defineProperty()方法。
十九、單頁面應用和多頁面應用區別及優缺點
單頁面應用(SPA),通俗一點說就是指只有一個主頁面的應用,瀏覽器一開始要加載所有必須的 html, js, css。所有的頁面內容都包含在這個所謂的主頁面中。但在寫的時候,還是會分開寫(頁面片段),然后在交互的時候由路由程序動態載入,單頁面的頁面跳轉,僅刷新局部資源。多應用于pc端。
多頁面(MPA),就是指一個應用中有多個頁面,頁面跳轉時是整頁刷新
單頁面的優點:
用戶體驗好,快,內容的改變不需要重新加載整個頁面,基于這一點spa對服務器壓力較小;前后端分離;頁面效果會比較炫酷(比如切換頁面內容時的專場動畫)。
單頁面缺點:
不利于seo;導航不可用,如果一定要導航需要自行實現前進、后退。(由于是單頁面不能用瀏覽器的前進后退功能,所以需要自己建立堆棧管理);初次加載時耗時多;頁面復雜度提高很多。
二十、v-if和v-for的優先級
當 v-if 與 v-for 一起使用時,v-for 具有比 v-if 更高的優先級,這意味著 v-if 將分別重復運行于每個 v-for 循環中。所以,不推薦v-if和v-for同時使用。
如果v-if和v-for一起用的話,vue中的的會自動提示v-if應該放到外層去。
二十一、assets和static的區別
答相同點:assets和static兩個都是存放靜態資源文件。項目中所需要的資源文件圖片,字體圖標,樣式文件等都可以放在這兩個文件下,這是相同點
不相同點:assets中存放的靜態資源文件在項目打包時,也就是運行npm run build時會將assets中放置的靜態資源文件進行打包上傳,所謂打包簡單點可以理解為壓縮體積,代碼格式化。而壓縮后的靜態資源文件最終也都會放置在static文件中跟著index.html一同上傳至服務器。static中放置的靜態資源文件就不會要走打包壓縮格式化等流程,而是直接進入打包好的目錄,直接上傳至服務器。因為避免了壓縮直接進行上傳,在打包時會提高一定的效率,但是static中的資源文件由于沒有進行壓縮等操作,所以文件的體積也就相對于assets中打包后的文件提交較大點。在服務器中就會占據更大的空間。
建議:將項目中template需要的樣式文件js文件等都可以放置在assets中,走打包這一流程。減少體積。而項目中引入的第三方的資源文件如iconfoont.css等文件可以放置在static中,因為這些引入的第三方文件已經經過處理,我們不再需要處理,直接上傳。
二十二、vue常用的修飾符
.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止執行預設的行為(如果事件可取消,則取消該事件,而不停止事件的進一步傳播);
.capture:與事件冒泡的方向相反,事件捕獲由外到內;
.self:只會觸發自己范圍內的事件,不包含子元素;
.once:只會觸發一次。
二十三、vue的兩個核心點
數據驅動、組件系統
1.數據驅動:ViewModel,保證數據和視圖的一致性。
2.組件系統:應用類UI可以看作全部是由組件樹構成的。
二十四、vue和jQuery的區別
jQuery是使用選擇器($)選取DOM對象,對其進行賦值、取值、事件綁定等操作,其實和原生的HTML的區別只在于可以更方便的選取和操作DOM對象,而數據和界面是在一起的。比如需要獲取label標簽的內容:$("lable").val();,它還是依賴DOM元素的值。
Vue則是通過Vue對象將數據和View完全分離開來了。對數據進行操作不再需要引用相應的DOM對象,可以說數據和View是分離的,他們通過Vue對象這個vm實現相互的綁定。這就是傳說中的MVVM。
二十五、引進組件的步驟
在template中引入組件;
在script的第一行用import引入路徑;
用component中寫上組件名稱。
二十六、delete和Vue.delete刪除數組的區別
delete只是被刪除的元素變成了 empty/undefined 其他的元素的鍵值還是不變。Vue.delete 直接刪除了數組 改變了數組的鍵值。
二十七、SPA首屏加載慢如何解決
1、盡可能的縮小webpack或者其他打包工具生成的包的大小
2、使用服務端渲染的方式
3、使用預渲染的方式
4、使用gzip減小網絡傳輸的流量大小
5、按照頁面或者組件分塊懶加載
6、異步路由加載
二十八、Vue-router跳轉和location.href有什么區別
使用location.href='/url'來跳轉,簡單方便,但是刷新了頁面;
使用history.pushState('/url'),無刷新頁面,靜態跳轉;
引進router,然后使用router.push('/url')來跳轉,使用了diff算法,實現了按需加載,減少了dom的消耗。
其實使用router跳轉和使用history.pushState()沒什么差別的,因為vue-router就是用了history.pushState(),尤其是在history模式下。
二十九、vue slot
簡單來說,假如父組件需要在子組件內放一些DOM,那么這些DOM是顯示、不顯示、在哪個地方顯示、如何顯示,就是slot分發負責的活。
三十、你們vue項目是打包了一個js文件,一個css文件,還是有多個文件?
根據vue-cli腳手架規范,一個js文件,一個CSS文件。
三十一、Vue里面router-link在電腦上有用,在安卓上沒反應怎么解決?
Vue路由在Android機上有問題,babel問題,安裝babel polypill插件解決。
三十三、Vue2中注冊在router-link上事件無效解決方法
使用@click.native。原因:router-link會阻止click事件,.native指直接監聽一個原生事件。
三十四、RouterLink在IE和Firefox中不起作用(路由不跳轉)的問題
方法一:只用a標簽,不適用button標簽;方法二:使用button標簽和Router.navigate方法
三十五、請說下封裝 vue 組件的過程?
1. 建立組件的模板,先把架子搭起來,寫寫樣式,考慮好組件的基本邏輯。
2.? 準備好組件的數據輸入。即分析好邏輯,定好 props 里面的數據、類型。
3.? 準備好組件的數據輸出。即根據組件邏輯,做好要暴露出來的方法。
4.? 封裝完畢了,直接調用即可
三十六、params和query的區別
用法:query要用path來引入,params要用name來引入,接收參數都是類似的,分別是this.$route.query.name和this.$route.params.name。
url地址顯示:query更加類似于我們ajax中get傳參,params則類似于post,說的再簡單一點,前者在瀏覽器地址欄中顯示參數,后者則不顯示
注意點:query刷新不會丟失query里面的數據
params刷新 會 丟失 params里面的數據。
三十七、vue初始化頁面閃動問題
使用vue開發時,在vue初始化之前,由于div是不歸vue管的,所以我們寫的代碼在還沒有解析的情況下會容易出現花屏現象,看到類似于{{message}}的字樣,雖然一般情況下這個時間很短暫,但是我們還是有必要讓解決這個問題的。
首先:在css里加上[v-cloak] {
display: none;
}。
如果沒有徹底解決問題,則在根元素加上style="display: none;" :style="{display: 'block'}"
三十八、vue更新數組時觸發視圖更新的方法
push();pop();shift();unshift();splice(); sort();reverse()
三九、vue常用的UI組件庫
Mint UI,element,VUX
四十、vue修改打包后靜態資源路徑的修改
cli2版本:將 config/index.js 里的 assetsPublicPath 的值改為 './' 。
build: {
...
assetsPublicPath: './',
...
}
cli3版本:在根目錄下新建vue.config.js 文件,然后加上以下內容:(如果已經有此文件就直接修改)
module.exports = {
publicPath: '', // 相對于 HTML 頁面(目錄相同)? ? ? }
四十一、vue.cli中怎樣使用自定義的組件?有遇到過哪些問題嗎?
第一步:在components目錄新建你的組件文件(smithButton.vue),script一定要export default {
第二步:在需要用的頁面(組件)中導入:import smithButton from ‘../components/smithButton.vue’
第三步:注入到vue的子組件的components屬性上面,components:{smithButton}
第四步:在template視圖view中使用,? 問題有:smithButton命名,使用的時候則smith-button。
四十二、聊聊你對Vue.js的template編譯的理解?
簡而言之,就是先轉化成AST樹,再得到的render函數返回VNode(Vue的虛擬DOM節點)
詳情步驟:
首先,通過compile編譯器把template編譯成AST語法樹(abstract
syntax tree
即源代碼的抽象語法結構的樹狀表現形式),compile是createCompiler的返回值,createCompiler是用以創建編譯器的。另外compile還負責合并option。
然后,AST會經過generate(將AST語法樹轉化成render funtion字符串的過程)得到render函數,render的返回值是VNode,VNode是Vue的虛擬DOM節點,里面有(標簽名、子節點、文本等等)
四十三、vuejs與angularjs以及react的區別?
1.與AngularJS的區別
相同點:
都支持指令:內置指令和自定義指令。
都支持過濾器:內置過濾器和自定義過濾器。
都支持雙向數據綁定。
都不支持低端瀏覽器。
不同點:
1.AngularJS的學習成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比較簡單、直觀。
2.在性能上,AngularJS依賴對數據做臟檢查,所以Watcher越多越慢。
Vue.js使用基于依賴追蹤的觀察并且使用異步隊列更新。所有的數據都是獨立觸發的。
對于龐大的應用來說,這個優化差異還是比較明顯的。
2.與React的區別
相同點:
React采用特殊的JSX語法,Vue.js在組件開發中也推崇編寫.vue特殊文件格式,對文件內容都有一些約定,兩者都需要編譯后使用。
中心思想相同:一切都是組件,組件實例之間可以嵌套。
都提供合理的鉤子函數,可以讓開發者定制化地去處理需求。
都不內置列數AJAX,Route等功能到核心包,而是以插件的方式加載。
在組件開發中都支持mixins的特性。
不同點:
React依賴Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM會對渲染出來的結果做臟檢查。
Vue.js在模板中提供了指令,過濾器等,可以非常方便,快捷地操作Virtual DOM。
四十四、虛擬Dom以及key屬性的作用
由于在瀏覽器中操作DOM是很昂貴的。頻繁的操作DOM,會產生一定的性能問題。這就是虛擬Dom的產生原因。
Vue2的Virtual
DOM借鑒了開源庫snabbdom的實現。Virtual
DOM本質就是用一個原生的JS對象去描述一個DOM節點。是對真實DOM的一層抽象。(也就是源碼中的VNode類,它定義在src/core/vdom/vnode.js中。)VirtualDOM映射到真實DOM要經歷VNode的create、diff、patch等階段。
「key的作用是盡可能的復用 DOM 元素。」
新舊
children 中的節點只有順序是不同的時候,最佳的操作應該是通過移動元素的位置來達到更新的目的。需要在新舊 children
的節點中保存映射關系,以便能夠在舊 children 的節點中找到可復用的節點。key也就是children中節點的唯一標識。
四十五、 請說出 vue-cli 工程中每個文件夾和文件的用處。
build 文件夾:存放 webpack 的相關配置以及腳本文件,在實際開發過程中只會偶爾用到webpack.base.conf.js,配置 less、babel 等。
config 文件夾:常用到此文件夾下的 config.js (index.js) 配置開發環境的端口號,是否開啟熱加載或者設置生產環境的靜態資源相對路徑、是否開啟 gzip 壓縮、npm run build 命令打包生成靜態資源的名稱和路徑等。
node_modules:存放 npm install 命令下載的開發環境和生產環境的各種依賴。
src文件夾 :工程項目的源碼以及資源、包括頁面圖片、路由組件、路由配置、vuex、入口文件等。其他文件:定義的一些項目信息,說明等等。
四十六、vue中解決跨域問題
方法1.后臺更改header
header('Access-Control-Allow-Origin:*');//允許所有來源訪問
header('Access-Control-Allow-Method:POST,GET');//允許訪問的方式
方法2.使用JQuery提供的jsonp
methods: {
? getData () {
? ? var self = this
? ? $.ajax({
? ? ? url: 'http://f.apiplus.cn/bj11x5.json',
? ? ? type: 'GET',
? ? ? dataType: 'JSONP',
? ? ? success: function (res) {
? ? ? ? self.data = res.data.slice(0, 3)
? ? ? ? self.opencode = res.data[0].opencode.split(',')
? ? ? }
? ? })
? }
}
方法3.使用http-proxy-middleware 代理解決(項目使用vue-cli腳手架搭建)
例如請求的url:“http://f.apiplus.cn/bj11x5.json”
1、打開config/index.js,在proxyTable中添寫如下代碼:
proxyTable: {
? '/api': {? //使用"/api"來代替"http://f.apiplus.c"
? ? target: 'http://f.apiplus.cn', //源地址
? ? changeOrigin: true, //改變源
? ? pathRewrite: {
? ? ? '^/api': 'http://f.apiplus.cn' //路徑重寫
? ? ? }
? }
}
2、使用axios請求數據時直接使用“/api”:
getData () {
axios.get('/api/bj11x5.json', function (res) {
?? console.log(res)
})
通過這中方法去解決跨域,打包部署時還按這種方法會出問題。解決方法如下:
let serverUrl = '/api/'? //本地調試時
// let serverUrl = 'http://f.apiplus.cn/'? //打包部署上線時
export default {
? dataUrl: serverUrl + 'bj11x5.json'
}
生命周期函數面試題
1.什么是 vue 生命周期?有什么作用?
每個
Vue 實例在被創建時都要經過一系列的初始化過程——例如,需要設置數據監聽、編譯模板、將實例掛載到 DOM 并在數據變化時更新 DOM
等。同時在這個過程中也會運行一些叫做 生命周期鉤子
的函數,這給了用戶在不同階段添加自己的代碼的機會。(ps:生命周期鉤子就是生命周期函數)例如,如果要通過某些插件操作DOM節點,如想在頁面渲染完后彈出廣告窗,
那我們最早可在mounted 中進行。
2.第一次頁面加載會觸發哪幾個鉤子?
beforeCreate, created, beforeMount, mounted
3.簡述每個周期具體適合哪些場景
beforeCreate:在new一個vue實例后,只有一些默認的生命周期鉤子和默認事件,其他的東西都還沒創建。在beforeCreate生命周期執行的時候,data和methods中的數據都還沒有初始化。不能在這個階段使用data中的數據和methods中的方法
create:data 和 methods都已經被初始化好了,如果要調用 methods 中的方法,或者操作 data 中的數據,最早可以在這個階段中操作
beforeMount:執行到這個鉤子的時候,在內存中已經編譯好了模板了,但是還沒有掛載到頁面中,此時,頁面還是舊的
mounted:執行到這個鉤子的時候,就表示Vue實例已經初始化完成了。此時組件脫離了創建階段,進入到了運行階段。 如果我們想要通過插件操作頁面上的DOM節點,最早可以在和這個階段中進行
beforeUpdate:當執行這個鉤子時,頁面中的顯示的數據還是舊的,data中的數據是更新后的, 頁面還沒有和最新的數據保持同步
updated:頁面顯示的數據和data中的數據已經保持同步了,都是最新的
beforeDestory:Vue實例從運行階段進入到了銷毀階段,這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于可用狀態。還沒有真正被銷毀
destroyed:這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于不可用狀態。組件已經被銷毀了。
4.created和mounted的區別
created:在模板渲染成html前調用,即通常初始化某些屬性值,然后再渲染成視圖。
mounted:在模板渲染成html后調用,通常是初始化頁面完成后,再對html的dom節點進行一些需要的操作。
5.vue獲取數據在哪個周期函數
一般 created/beforeMount/mounted 皆可.
比如如果你要操作 DOM , 那肯定 mounted 時候才能操作.
6.請詳細說下你對vue生命周期的理解?
總共分為8個階段創建前/后,載入前/后,更新前/后,銷毀前/后。
創建前/后:在beforeCreated階段,vue實例的掛載元素$el和**數據對象**data都為undefined,還未初始化。在created階段,vue實例的數據對象data有了,$el還沒有。
載入前/后:在beforeMount階段,vue實例的$el和data都初始化了,但還是掛載之前為虛擬的dom節點,data.message還未替換。在mounted階段,vue實例掛載完成,data.message成功渲染。
更新前/后:當data變化時,會觸發beforeUpdate和updated方法。
銷毀前/后:在執行destroy方法后,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,但是dom結構依然存在。
vue路由面試題
1.mvvm 框架是什么?
vue是實現了雙向數據綁定的mvvm框架,當視圖改變更新模型層,當模型層改變更新視圖層。在vue中,使用了雙向綁定技術,就是View的變化能實時讓Model發生變化,而Model的變化也能實時更新到View。
2.vue-router 是什么?它有哪些組件
vue用來寫路由一個插件。router-link、router-view
3.active-class 是哪個組件的屬性?
vue-router模塊的router-link組件。children數組來定義子路由
4.怎么定義 vue-router 的動態路由? 怎么獲取傳過來的值?
在router目錄下的index.js文件中,對path屬性加上/:id。? 使用router對象的params.id。
5.vue-router 有哪幾種導航鉤子?
三種,
第一種:是全局導航鉤子:router.beforeEach(to,from,next),作用:跳轉前進行判斷攔截。
第二種:組件內的鉤子
第三種:單獨路由獨享組件
6.$route 和 $router 的區別
$router是“路由實例”對象,即使用 new VueRouter創建的實例,包括了路由的跳轉方法,鉤子函數等。在script標簽中想要導航到不同的URL,使用$router.push方法。返回上一個歷史history用$router.to(-1)
$route為當前router跳轉對象。里面可以獲取當前路由的name,path,query,parmas等。
7.vue-router的兩種模式
hash模式:即地址欄 URL 中的 # 符號;
history模式:window.history對象打印出來可以看到里邊提供的方法和記錄長度。利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定瀏覽器支持)。
8.vue-router實現路由懶加載( 動態加載路由 )
三種方式,
第一種:vue異步組件技術 ==== 異步加載,vue-router配置路由 , 使用vue的異步組件技術 , 可以實現按需加載 .但是,這種情況下一個組件生成一個js文件。
第二種:路由懶加載(使用import)。
第三種:webpack提供的require.ensure(),vue-router配置路由,使用webpack的require.ensure技術,也可以實現按需加載。這種情況下,多個路由指定相同的chunkName,會合并打包成一個js文件。
vuex常見面試題
1.vuex是什么?怎么使用?哪種功能場景使用它?
vue框架中狀態管理。在main.js引入store,注入。
新建了一個目錄store.js,….. export 。
場景有:單頁應用中,組件之間的狀態。音樂播放、登錄狀態、加入購物車
2.vuex有哪幾種屬性?
有五種,分別是 State、 Getter、Mutation 、Action、 Module
state=> 基本數據(數據源存放地)
getters=> 從基本數據派生出來的數據
mutations=> 提交更改數據的方法,同步!
actions=> 像一個裝飾器,包裹mutations,使之可以異步。
modules=> 模塊化Vuex
3.Vue.js中ajax請求代碼應該寫在組件的methods中還是vuex的actions中?
如果請求來的數據是不是要被其他組件公用,僅僅在請求的組件內使用,就不需要放入vuex 的state里。
如果被其他地方復用,這個很大幾率上是需要的,如果需要,請將請求放入action里,方便復用。