常見Vue原理面試題

1. Vue的響應式原理是什么?請詳細說明Object.defineProperty()和Proxy的區別和用法。

響應式原理:Vue中采用了數據劫持的方式,通過Object.defineProperty()函數來監聽數據變化,并在數據變化時觸發對應的更新函數。 Object.defineProperty()與Proxy的區別:前者只能監聽屬性的讀取和修改,后者可以監聽數組的變化等更多場景,且性能更高。


// 實現observe函數,對data對象中的所有屬性進行數據劫持
function observe(data) {if (!data || typeof data !== 'object') {return}Object.keys(data).forEach(key => {defineReactive(data, key, data[key])})
}// 定義defineReactive函數,通過Object.defineProperty()函數來監聽數據變化
function defineReactive(obj, key, val) {observe(val)Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter() {console.log('get value:', val)return val},set: function reactiveSetter(newVal) {console.log('set value:', newVal)val = newVal}})
}// 測試代碼
const obj = { name: 'Tom', age: 18 }
observe(obj)
obj.age = 20
console.log(obj.age) // 輸出:20

2. Vue的模板編譯原理是什么?請說明它的優化策略和實現方式。并手動實現一個簡單的模板編譯器。

模板編譯原理:Vue中將用戶寫好的模板轉換成渲染函數,實際渲染時調用該函數進行渲染。模板編譯主要包括三個階段:解析、優化和生成。

優化策略:Vue在模板編譯階段會對模板進行靜態節點標記和靜態根節點標記,從而可以避免不必要的重復渲染和提升整體渲染性能。

實現方式:Vue通過將模板解析成抽象語法樹(AST),再轉換成render函數的方式來實現模板編譯。最終生成的render函數就是一個虛擬DOM的描述對象,然后通過虛擬DOM的diff算法進行渲染更新。

// 簡化版的 Vue 模板編譯器
function compile(template) {var element = document.createElement('div');element.innerHTML = template;Array.from(element.childNodes).forEach(function(node) {if (node.nodeType === Node.TEXT_NODE) {var reg = /\{\{(.+)\}\}/;var match = node.textContent.match(reg);if (match) {var key = match[1].trim();node.textContent = '{{' + key + '}}';node._key = key;}} else if (node.nodeType === Node.ELEMENT_NODE) {Array.from(node.attributes).forEach(function(attr) {if (attr.name.startsWith('v-')) {if (attr.name === 'v-model') {node.value = '';node.addEventListener('input', function(event) {vm[attr.value] = event.target.value;});}node.removeAttribute(attr.name);}});}if (node.childNodes.length > 0) {compile(node.innerHTML);}});return element.innerHTML;
}var vm = new Vue({el: '#app',data: {message: 'Hello, World!'},template: '<div><h1>{{message}}</h1></div>'
});document.getElementById('app').innerHTML = compile(vm.template);

?

3. Vue中的虛擬DOM算法是什么?請說明其原理和優化策略。

虛擬DOM算法:Vue中通過比較新舊虛擬DOM樹之間的差異來最小化更新操作,從而提高渲染效率。虛擬DOM算法主要包括兩個步驟:Diff算法和更新操作。

原理:Vue將模板編譯成虛擬DOM樹,并將其與上一個虛擬DOM樹進行比較,找出需要更新的節點并進行更新操作。

優化策略:Vue采用了一些策略來減少比較的次數,優化了虛擬DOM樹的構建和比較的性能。


// 舊的虛擬DOM樹
const prevVNode = {tag: 'div',props: { id: 'container' },children: [{ tag: 'h1', children: 'Hello, World!' },{ tag: 'p', children: 'Welcome to my website.' }]
}// 新的虛擬DOM樹
const nextVNode = {tag: 'div',props: { id: 'container' },children: [{ tag: 'h1', children: 'Hello, Vue!' },{ tag: 'p', children: 'Welcome to the Vue world.' }]
}// 執行diff算法,得到需要更新的節點
function diff(prevVNode, nextVNode) {if (prevVNode.tag === nextVNode.tag) {const patchProps = {}const prevChildren = prevVNode.childrenconst prevProps = prevVNode.propsconst nextChildren = nextVNode.childrenconst nextProps = nextVNode.props// diff propsfor (const key in nextProps) {const prevVal = prevProps[key]const nextVal = nextProps[key]if (prevVal !== nextVal) {patchProps[key] = nextVal}}// diff childrenif (prevChildren.length !== nextChildren.length) {patchProps.children = nextChildren} else {const patchChildren = []for (let i = 0; i < nextChildren.length; i++) {const childPatch = diff(prevChildren[i], nextChildren[i])patchChildren.push(childPatch)}patchProps.children = patchChildren}return { type: 'update', props: patchProps }} else {return { type: 'replace', node: nextVNode }}
}// 執行更新操作,將差異應用到真實DOM樹上
function patch(node, patchProps) {switch (patchProps.type) {case 'replace':const newNode = createDOMElement(patchProps.node)node.parentNode.replaceChild(newNode, node)breakcase 'update':updateDOMProps(node, patchProps.props)for (const patchChild of patchProps.children) {patch(node.children[patchChild.index], patchChild.props)}break}
}

?

4. Vue中的組件通信有哪些方式?請分別說明它們的特點和應用場景。

組件通信方式:

  1. 父子組件通信:通過props傳遞數據和事件監聽。 特點:簡單易用,適用于父子組件之間的數據交互。 應用場景:父子組件之間的狀態傳遞和操作。

  2. 子父組件通信:通過 $emit 觸發自定義事件和 $on 監聽事件。 特點:適用于子組件向父組件傳遞數據和狀態變更。 應用場景:子組件向父組件傳遞用戶輸入或其他數據。

  3. 兄弟組件通信:通過$emit/ $on或vuex進行數據共享。 特點:適用于兄弟組件之間的狀態共享和協同工作。 應用場景:多個組件之間需要共享狀態或數據。

  4. 跨級組件通信:通過provide/ inject進行跨級數據傳遞。 特點:適用于祖先組件向后代組件傳遞數據。 應用場景:多級嵌套組件之間的狀態共享和傳遞。


// 子組件
<template><div><h1>{{ title }}</h1><button @click="handleClick">點擊我</button></div>
</template>
<script>
export default {props: ['title'],methods: {handleClick() {this.$emit('change', '子組件按鈕被點擊了')}}
}
</script>// 父組件
<template><div><h2>{{ subtitle }}</h2><child :title="title" @change="handleChange"></child></div>
</template>
<script>
import Child from './Child.vue'
export default {components: { Child },data() {return {title: '父子組件通信示例',subtitle: ''}},methods: {handleChange(msg) {this.subtitle = msg}}
}
</script>

?

5. Vue中的v-model指令在表單元素上的使用方式有哪些?請分別說明它們的區別和注意事項。

v-model指令在表單元素上的使用方式:

  1. v-model="value":用于單選框、復選框和選擇框的數據綁定,綁定的是選擇的值。 區別:單選框和復選框綁定的是選中狀態,而選擇框綁定的是選中的值。 注意事項:當多個單選框或復選框綁定同一個數據時,需要為每個元素添加不同的value屬性。

  2. v-model="value":用于輸入框等表單元素的雙向數據綁定,綁定的是輸入框的值。 區別:v-model與value屬性的實現方式不同,v-model實現了雙向綁定的效果。 注意事項:需要為輸入框添加type屬性,并且該元素必須支持input事件或change事件。


// 單選框
<template><div><input type="radio" v-model="gender" value="male">男<input type="radio" v-model="gender" value="female">女</div>
</template>
<script>
export default {data() {return {gender: ''}}
}
</script>// 輸入框
<template><div><input type="text" v-model="message"><p>輸入的內容是:{{ message }}</p></div>
</template>
<script>
export default {data() {return {message: ''}}
}
</script>

?

6. Vue中的計算屬性computed和偵聽器watch有什么區別?請舉例說明它們的使用場景。

computed和watch的區別:

  1. computed是基于依賴緩存的,只有當依賴的數據發生變化時才會重新計算;watch則是通過監聽數據變化來觸發回調函數。
  2. computed適用于多個值之間的計算和處理,而watch則適用于單獨的數據變化后執行異步或復雜的操作。

// 計算屬性
<template><div><p>商品數量:{{ quantity }}</p><p>商品總價:{{ totalPrice }}</p></div>
</template>
<script>
export default {data() {return {price: 10,quantity: 3}},computed: {totalPrice() {return this.price * this.quantity}}
}
</script>// 偵聽器
<template><div><input type="text" v-model="message"><p>輸入的消息是:{{ message }}</p></div>
</template>
<script>
export default {data() {return {message: ''}},watch: {message(newVal, oldVal) {console.log('輸入的消息發生了變化:', newVal, oldVal)// 執行異步操作this.$http.get('/api/messages', { params: { message: newVal } }).then(res => {console.log(res.data)})}}
}
</script>

7. 簡述 Vue 中的異步更新隊列原理。

Vue 在更新視圖時會將所有數據變化的 watcher(觀察者)加入到一個異步更新隊列中,等到下一個事件循環時才執行更新操作。這樣做的好處是避免頻繁的更新視圖,提高性能。

  1. 在 watcher 對象構造函數中,將當前 watcher 對象 push 到全局的異步更新隊列 queue 中;
  2. 在下一個事件循環方式中,通過 flushQueue 函數逐個遍歷 queue 數組中的 watcher,調用其 run 方法進行更新;
  3. 清空 queue 數組,以待下一次更新。
// 定義全局異步更新隊列
var queue = [];// 異步更新隊列處理函數
function flushQueue() {queue.forEach(function(watcher) {watcher.run();});queue = [];
}// 定義 Watcher 類
class Watcher {constructor() {queue.push(this); // 將當前 watcher 加入到異步更新隊列中}run() {console.log('更新視圖!'); // 執行更新操作}
}// 創建多個 Watcher 對象
var watcher1 = new Watcher();
var watcher2 = new Watcher();// 延遲一定時間,再執行異步更新操作
setTimeout(function() {flushQueue(); // 清空異步更新隊列,逐個執行更新
}, 0);

?

8. 簡述 Vue 中的事件機制原理,并手動實現一個簡單的事件總線。

Vue 中的事件機制是利用事件總線 EventBus 進行封裝實現的。事件總線將事件的發送和接收解耦,通過一個中心化的事件分發器(Event Bus)來管理,使得多個組件間的通信變得簡單而靈活。

// 定義 EventBus 類
class EventBus {constructor() {this.events = {};}$on(name, callback) {if (!this.events[name]) {this.events[name] = [];}this.events[name].push(callback);}$emit(name, ...args) {if (this.events[name]) {this.events[name].forEach(function(callback) {callback(...args);});}}
}// 創建 EventBus 實例
var bus = new EventBus();// 定義事件處理函數
function handleMessage(message) {console.log(`收到消息:${message}`);
}// 綁定 message 事件處理函數
bus.$on('message', handleMessage);// 觸發 message 事件,并傳遞參數
bus.$emit('message', 'Hello, World!');

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717370.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717370.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717370.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringCloud負載均衡源碼解析 | 帶你從表層一步步剖析Ribbon組件如何實現負載均衡功能

目錄 1、負載均衡原理 2、源碼分析 2.1、LoadBalanced 2.2、LoadBalancerClient 2.3、RibbonAutoConfiguration 2.4、LoadBalancerAutoConfiguration 2.5、LoadBalancerIntercepor? 2.6、再回LoadBalancerClient 2.7、RibbonLoadBalancerClient 2.7.1、DynamicServe…

OpenCV 4基礎篇| OpenCV圖像的拼接

目錄 1. Numpy (np.hstack&#xff0c;np.vstack)1.1 注意事項1.2 代碼示例 2. matplotlib2.1 注意事項2.2 代碼示例 3. 擴展示例&#xff1a;多張小圖合并成一張大圖4. 總結 1. Numpy (np.hstack&#xff0c;np.vstack) 語法結構&#xff1a; retval np.hstack(tup) # 水平…

工作日記:JavaScript fill() 方法

定義 fill() 方法用于將一個固定值替換數組的元素。 語法 array.fill(value, start, end) value&#xff1a;必填。要填充的值 start&#xff1a;可選。開始填充位置 end&#xff1a;可選。結束填充位置&#xff08;默認是數組的長度&#xff1a;array.length&#xff09;…

提取拼多多店鋪商家電話的爬蟲軟件

拼多多是中國知名的團購電商平臺&#xff0c;許多用戶在購物時都希望能夠直接聯系到店鋪商家&#xff0c;以便獲得更多的產品信息或解決問題。在這篇文章中&#xff0c;我們將介紹如何使用Python編寫一個爬蟲軟件&#xff0c;來提取拼多多店鋪商家電話。 首先&#xff0c;我們…

c++之通訊錄管理系統

1&#xff0c;系統需求 通訊錄是一個記錄親人&#xff0c;好友信息的工具 系統中需要實現的功能如下&#xff1a; 1&#xff0c;添加聯系人&#xff1a;向通訊錄中添加新人&#xff0c;信息包括&#xff08;姓名&#xff0c;性別&#xff0c;年齡&#xff0c;聯系電話&#…

構建高效的接口自動化測試框架思路

在選擇接口測試自動化框架時&#xff0c;需要根據團隊的技術棧和項目需求來綜合考慮。對于測試團隊來說&#xff0c;使用Python相關的測試框架更為便捷。無論選擇哪種框架&#xff0c;重要的是確保 框架功能完備&#xff0c;易于維護和擴展&#xff0c;提高測試效率和準確性。今…

IntelliJ IDEA 的常用快捷鍵

IntelliJ IDEA 的常用快捷鍵非常多&#xff0c;這些快捷鍵可以幫助你更高效地編寫代碼。以下是一些常用的快捷鍵總結&#xff1a; 基礎操作 CtrlN&#xff1a;查找類CtrlShiftN&#xff1a;查找文件CtrlAltL&#xff1a;格式化代碼AltInsert&#xff1a;生成代碼&#xff08;…

信息安全技術第1章——信息網絡安全基本概念

課程介紹 網絡信息安全是醫學信息工程專業的限選課。主要圍繞計算機網絡安全所涉及的主要問題進行講解&#xff0c;內容包括&#xff1a;對稱密碼與公鑰密碼的基本原理、相關算法及應用。電子郵件的安全&#xff0c;IP安全&#xff0c;Web安全&#xff0c;惡意軟件及防火墻等內…

UI自動化-(web端窗口截圖文件上傳-實操入門)

1、窗口截圖 1. UI自動化中&#xff0c;為什么需要進行窗口截圖&#xff1f; 調試和故障排除&#xff1a;截圖可以直觀地查看界面的狀態&#xff0c;快速識別和解決問題。當自動化過程中出現錯誤或異常時&#xff0c;通過查看截圖可以確定是否是界面元素的問題&#xff0c;例…

C++ opencv 學習

文章目錄 1、創建窗口2、讀取圖片3、視頻采集4、Mat的使用5、異或操作6、通道分離&#xff0c;通道合并7、色彩空間轉換8、最大值、最小值9、繪制圖像10、多邊形繪制11、隨機數12、鼠標實時繪制矩形13、歸一化14、resize操作15、旋轉翻轉16、視頻操作17、模糊操作18、高斯模糊操…

SpringBoot整合MyBatis實現增刪改查

?作者簡介:大家好,我是Leo,熱愛Java后端開發者,一個想要與大家共同進步的男人???? ??個人主頁:Leo的博客 ??當前專欄: 循序漸進學SpringBoot ?特色專欄: MySQL學習 ??本文內容: SpringBoot整合MyBatis實現增刪改查 ??個人知識庫: Leo知識庫,歡迎大家訪…

mysql之 case when

1 簡單 case 函數&#xff0c;IF函數 格式&#xff1a; CASE input_expression WHEN when_expression THENresult_expression [...n ] [ ELSEelse_result_expression ENDIF(條件,True結果,False結果)2 條件表達式 可嵌套多層&#xff0c;類似于 if … else if … else … end…

Java進階-IO(1)

進入java IO部分的學習&#xff0c;首先學習IO基礎&#xff0c;內容如下。需要了解流的概念、分類還有其他一些如集合與文件的轉換&#xff0c;字符編碼問題等&#xff0c;這次先學到字節流的讀寫數據&#xff0c;剩余下次學完。 一、IO基礎 1、背景 1.1 數據存儲問題 變量…

代碼隨想錄day11(1)字符串:反轉字符串中的單詞 (leetcode151)

題目要求&#xff1a;給定一個字符串&#xff0c;將其中單詞順序反轉&#xff0c;且每個單詞之間有且僅有一個空格。 思路&#xff1a;因為本題沒有限制空間復雜度&#xff0c;所以首先想到的是用split直接分割單詞&#xff0c;然后將單詞倒敘相加。 但如果想讓空間復雜度為O…

芯來科技發布最新NI系列內核,NI900矢量寬度可達512/1024位

參考&#xff1a;芯來科技發布最新NI系列內核&#xff0c;NI900矢量寬度可達512/1024位 (qq.com) 本土RISC-V CPU IP領軍企業——芯來科技正式發布首款針對人工智能應用的專用處理器產品線Nuclei Intelligence(NI)系列&#xff0c;以及NI系列的第一款AI專用RISC-V處理器CPU IP…

反向迭代器

反向迭代器 以list為例,我們完全可以再添加一個__list_reverse_iterator結構體,只需要修改和–的邏輯 template <class T, class Ref, class Ptr> struct __list_reverse_iterator {...self& operator(){_node _node->_prev;return *this;}self operator(int){…

Android 14.0 Launcher3定制化之桌面分頁橫線改成圓點顯示功能實現

1.前言 在14.0的系統rom產品定制化開發中&#xff0c;在進行launcher3的定制化中&#xff0c;在雙層改為單層的開發中&#xff0c;在原生的分頁 是橫線&#xff0c;而為了美觀就采用了系統原來的另外一種分頁方式&#xff0c;就是圓點比較美觀&#xff0c;接下來就來分析下相關…

網絡爬蟲部分應掌握的重要知識點

目錄 一、預備知識1、Web基本工作原理2、網絡爬蟲的Robots協議 二、爬取網頁1、請求服務器并獲取網頁2、查看服務器端響應的狀態碼3、輸出網頁內容 三、使用BeautifulSoup定位網頁元素1、首先需要導入BeautifulSoup庫2、使用find/find_all函數查找所需的標簽元素 四、獲取元素的…

基于springboot+vue的健身房管理系統

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

●139.單詞拆分 ● 關于多重背包,你該了解這些! ●背包問題總結篇!

●139.單詞拆分 物品&#xff1a;wordDict里面的單詞&#xff1b;背包容量&#xff1a;s.size()。 1.dp[j]含義。dp[j]true表示字符串前j個可以拆分成字典中的單詞。dp[s.size()] 就是最后的結果&#xff0c;整個字符串能&#xff08;true&#xff09;不能&#xff08;false…