Vue2 基礎面試題

v-show 和 v-if 區別

  • v-show 通過 CSS display 控制顯示和隱藏
  • v-if 通過判斷組件真實渲染和銷毀,而不是顯示和隱藏
  • 頻繁切換顯示狀態用 v-show,否則用 v-if

v-if

  • v-ifv-for 一起使用時,v-for 具有比 v-if 更高的優先級,意味著:v-if 將分別重復運行于每個 v-for 循環中,會造成性能問題。所以,不推薦 v-ifv-for 同時使用
const compiler = require('vue-template-compiler')const res = compiler.compile(`<div v-if="true" v-for="i in 3">{{message}}</div>`)with (this) {return renderList(3, function(i) {return true ? createElement('div', [createTextVNode(toString(message))]) : createEmptyVNode()})
}


v-show

const compiler = require('vue-template-compiler')const res = compiler.compile(`<p v-show="flag === 'a'">A</p>`)with (this) {return createElement('p',{directives: [{ name: 'show', rawName: 'v-show', value: flag === 'a', expression: "flag === 'a'" },],},[createTextVNode('A')])
}// v-show 操作的是樣式 https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/directives/show.js
bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {vnode = locateNode(vnode)const transition = vnode.data && vnode.data.transitionconst originalDisplay = el.__vOriginalDisplay =el.style.display === 'none' ? '' : el.style.displayif (value && transition) {vnode.data.show = trueenter(vnode, () => {el.style.display = originalDisplay})} else {el.style.display = value ? originalDisplay : 'none'}
}


為何在 v-for 中用 key

  • 必須用 key,且不能是 index 和 random
  • diff 算法中通過 tag 和 key 來判斷,是否是 sameNode
  • 減少渲染次數,提升渲染性能

描述 Vue 組件生命周期(父子組件)

  • beforeCreate 在初始化事件生命周期之后,數據被觀測(observer)之前調用
  • created 實例已經創建完成之后被調用
  • 可以進行一些數據、資源請求。在這個階段無法與 DOM 進行交互,如果非想要,可以通過 $nextTick 訪問
  • beforeMount 在 DOM 掛載之前被調用,相關的 render 函數首次被調用(如果有 template 會轉換成 render 函數)
  • 在此時也可以對數據進行更改,不會觸發 updated
  • mounted 創建 vm.$el 并替換 el,并在掛載之后調用該鉤子
  • 可以訪問到 DOM 節點,使用 $refs 屬性對 DOM 進行操作,也可以像后臺發送請求,拿到返回數據
  • beforeUpdate 數據更新時調用,發生在虛擬 DOM 重新渲染和和打補丁之前
  • 可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重新渲染
  • updated 由于數據更改導致虛擬 DOM 重新渲染和打補丁,在這之后會調用該鉤子
  • 避免在此期間更改狀態,可能會導致更新無限循環
  • beforeDestroy 實例銷毀之前調用
  • destroyed Vue 實例銷毀后調用,調用后,Vue 實例所有東西都會解綁定,所有事件監聽會被移除,所有子實例也會被銷毀可以執行一些優化操作,清除定時器,解除綁定事件

注意:除了 beforeCreate 和 created 鉤子之外,其他鉤子均在服務器端渲染期間不調用

Vue.prototype._init = function (options?: Object) {// ...initLifecycle(vm)initEvents(vm) // 初始化事件相關的屬性initRender(vm) // vm 添加了一些虛擬 dom、slot 等相關的屬性和方法callHook(vm, 'beforeCreate')initInjections(vm)initState(vm) // props、methods、data、watch、computed等數據初始化initProvide(vm)callHook(vm, 'created')
}


mounted (渲染完成)執行順序是先子后父

function patch(oldVnode, vnode, hydrating, removeOnly) {// 定義收集所有組件的insert hook方法的數組const insertedVnodeQueue = []if (isUndef(oldVnode)) {createElm(vnode, insertedVnodeQueue)}
}
function createElm(vnode, insertedVnodeQueue, ...) {// createChildren會遞歸創建子組件(遞歸createElm)createChildren(vnode, children, insertedVnodeQueue)if (isDef(data)) {// 執行所有的create鉤子invokeCreateHooks(vnode, insertedVnodeQueue)}
}
function invokeCreateHooks (vnode, insertedVnodeQueue) {// 把vnode push到insertedVnodeQueueif (isDef(i.insert)) insertedVnodeQueue.push(vnode)
}// 調用insert方法把DOM插入到父節點,因為是遞歸調用,子元素會優先調用insert
insert(parentElm, vnode.elm, refElm)
function invokeInsertHook(vnode, queue, initial) {// 依次調用insert方法queue[i].data.hook.insert(queue[i])
}
const componentVNodeHooks = {// 依次執行 mounted 方法insert(vnode: MountedComponentVNode) {callHook(componentInstance, 'mounted')},
}


$destroy (銷毀完成)執行順序是先子后父

Vue.prototype.$destroy = function() {callHook(vm, 'beforeDestroy')// 遞歸觸發子組件銷毀鉤子函數vm.__patch__(vm._vnode, null)callHook(vm, 'destroyed')
}


Vue 組件如何通訊

  • 父 -> 子通過 props,子 -> 父通過 $on $emit
  • 在父組件中提供數據子組件進行消費 provide、inject
  • ref 獲取實例的方式調用組件的屬性或方法
  • 自定義事件 event.$on、event.$off、event.$emit
  • vuex 狀態管理實現通信

描述組件渲染和更新過程

  • 生成 render 函數,其生成一個 vnode,它會 touch 觸發 getter 進行收集依賴
  • 在模板中哪個被引用了就會將其用 Watcher 觀察起來,發生了 setter 也會將其 Watcher 起來
  • 如果之前已經被 Watcher 觀察起來,發生更新進行重新渲染

雙向數據綁定 v-model 的實現原理

v-model本質上是語法糖,v-model 在內部為不同的輸入元素使用不同的屬性并拋出不同的事件

  • text 和 textarea 元素使用 value 屬性和 input 事件
  • checkbox 和 radio 使用 checked 屬性和 change 事件
  • select 字段將 value 作為 prop 并將 change 作為事件
const compiler = require('vue-template-compiler')const res = compiler.compile(`<input v-model="name" type="text" />`)with (this) {return createElement('input', {directives: [{ name: 'model', rawName: 'v-model', value: name, expression: 'name' }],attrs: { type: 'text' },domProps: { value: name },on: {input: function($event) {if ($event.target.composing) returnname = $event.target.value},},})
}


對 MVVM 的理解

  • Model:代表數據模型,也可以在 Model 中定義數據修改和操作的業務邏輯。我們可以把 Model 稱為數據層,因為它僅僅關注數據本身,不關心任何行為
  • View:用戶操作界面。當 ViewModel Model 進行更新的時候,會通過數據綁定更新到 View
  • ViewModel:業務邏輯層,View 需要什么數據,ViewModel 要提供這個數據;View 有某些操作,ViewModel 就要響應這些操作

總結: MVVM模式簡化了界面與業務的依賴,解決了數據頻繁更新。MVVM 在使用當中,利用雙向綁定技術,使得 Model 變化時,ViewModel 會自動更新,而 ViewModel 變化時,View 也會自動變化

computed 和 watch 的區別

computed

  • computed 具有緩存性,computed 的值在 getter 執行后是會緩存的,只有它依賴的屬性值改變之后,下一次獲取 computed 的值時才會重新調用對應的 getter 來計算
  • computed 適用于比較消耗性能的計算場景,可以提高性能

watch

  • 更多的是觀察作用,類似于數據監聽的回調函數,用于觀察 props$emit 或本組件的值,當數據變化時來執行回調進行后續操作
  • 無緩存性,頁面重新渲染時值不變化也會執行

computed watch 都支持對象的寫法

vm.$watch('obj', {deep: true, // 深度遍歷immediate: true, // 立即觸發handler: function(val, oldVal) {}, // 執行的函數
})
var vm = new Vue({data: { a: 1 },computed: {aPlus: {// this.aPlus 時觸發get: function() {return this.a + 1},// this.aPlus = 1 時觸發set: function(v) {this.a = v - 1},},},
})

為何組件 data 必須是一個函數

  • 一個組件被復用多次的話,也就是創建多個實例。本質上,這些實例用的都是同一個構造函數,如果 data 是對象的話(引用數據類型),會影響到所有實例
  • 為了組件不同實例 data 不沖突,data 必須是一個函數

自定義 v-model

v-model 可以看成是 value + input 方法的語法糖

  • 自定義:自己寫 model 屬性,里面放上 prop event
<template><input type="text" :value="text" @input="$emit('change', $event.target.value)" />
</template><script>
export default {model: {prop: 'text',event: 'change',},props: {text: String,},
}
</script>


相同邏輯如何抽離

  • Vue.mixin ,給組件每個生命周期、函數都混入一些公共邏輯
  • mixin 混入的鉤子函數會先于組件內的鉤子函數執行,并且在遇到同名選項時也會有選擇性進行合并

何時使用異步組件

核心就是把組件變成一個函數,依賴 import() 語法,可以實現文件的分割加載

  • 加載大組件
  • 路由異步加載

何時使用 keep-alive

常用的兩個屬性:includeexclude,允許組件有條件的進行緩存

兩個生命周期:activateddeactivated,用來得知當前組件是否處于活躍狀態

  • 緩存組件實例,用于保留組件狀態或避免重復渲染
  • 多個靜態 Tab 頁的切換時,來優化性能

何時需要使用 beforeDestory

  • 解綁自定義事件 event.$off
  • 清除定時器
  • 解綁自定義的 DOM 事件,如:windowscroll

action 和 mutation 有何區別

  • action 中可以處理異步,mutation 中不可以
  • mutation 做的是原子操作,action 可以整合多個 mutation

vue-router 常用的路由模式

hash 路由

  • hash 變化會觸發網頁跳轉,即瀏覽器的前進、后退
  • hash 變化不會刷新頁面,SPA 必需的特點
  • hash 永遠不會提交到 server 端(前端自生自滅)

history 路由

  • url 規范的路由,但跳轉時不刷新頁面
  • 需要 server 端配合,可參考:后端配置例子
  • pushState 不會觸發 hashchange 事件,popstate 事件只會在瀏覽器某些行為下觸發,比如點擊后退、前進按鈕

vnode 描述一個 DOM 結構

  • Vue 中的真實 DOM
<div id="div1" class="container"><p>vdom</p><ul style="font-size: 20px;"><li>a</li></ul>
</div>

  • Vue 中的虛擬 DOM
{tag: 'div',props: {className: 'container',id: 'div1',},children: [{tag: 'p',children: 'dom',},{tag: 'ul',props: { style: 'font-size: 20px' },children: [{ tag: 'li', children: 'a' }],},],
}


數據響應式原理

核心 API:Object.defineProperty

  • 存在一些問題,Vue 3.0 啟動 Proxy
  • Proxy 可以原生支持監聽數組變化
  • 但是 Proxy 兼容性不好,且無法 polyfill

問題

  • 深度監聽,需要遞歸到底,一次性計算量大
  • 無法監聽新增屬性/刪除屬性(Vue.setVue.delete
  • 不能監聽數組變化(重新定義原型,重寫 pushpop 等方法)

簡單實現 Vue 中的 defineReactive

// 觸發更新視圖
function updateView() {console.log('視圖更新')
}// 重新定義數組原型
const arrayProto = Array.prototype
// 創建新對象,原型指向 arrayProto ,再擴展新的方法不會影響原型
const arrayMethods = Object.create(arrayProto)
;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {arrayMethods[method] = function() {arrayProto[method].call(this, ...arguments) // 原始操作updateView() // 觸發視圖更新}
})// 重新定義屬性,監聽起來
function defineReactive(target, key, value) {observer(value) // 進行監聽// 不可枚舉的不用監聽const property = Object.getOwnPropertyDescriptor(target, key)if (property && property.configurable === false) returnObject.defineProperty(target, key, {get() {return value},set(newValue) {if (newValue !== value) {observer(newValue) // 值修改后進行監聽// value 一直在閉包中,此處設置完之后,再 get 時也是會獲取最新的值value = newValueupdateView() // 觸發更新視圖}},})
}// 監測數據的變化
function observer(target) {// 不是對象或數組(vue 是判斷是否是數組、純粹對象、可擴展對象)if (typeof target !== 'object' || target === null) {return target}// 不要這樣寫,污染全局的 Array 原型/* Array.prototype.push = function () {updateView()} */if (Array.isArray(target)) {target.__proto__ = arrayMethods}// 重新定義各個屬性(for in 也可以遍歷數組)for (let key in target) {if (!Object.hasOwnProperty.call(target, key)) returndefineReactive(target, key, target[key])}
}const data = {name: 'zhangsan',age: 20,info: {address: '北京', // 需要深度監聽},nums: [10, 20, 30],
}observer(data)data.name = 'lisi'
data.age = 21
data.info.address = '上海' // 深度監聽
// data.x = '100' // 新增屬性,監聽不到 —— 所以有 Vue.set
// delete data.name // 刪除屬性,監聽不到 —— 所有已 Vue.delete
data.nums.push(4) // 監聽數組


diff 算法

diff 算法過程:

  • 同級元素進行比較,再比較子節點
  • 先判斷一方有子節點,一方沒有子節點情況(如果新的 children 沒有子節點,將舊的子節點移除)
  • 之后比較都有子節點的情況(核心 diff),遞歸比較子節點

正常 diff 兩個樹的時間復雜度是 O(n^3),但實際情況我們很少會跨級移動 DOM。所以,只有當新舊 children 都為多個子節點時才需要核心的 diff 算法進行同層級比較

  • Vue2 核心 diff 算法采用了雙端比較的算法,同時從新舊 children 的兩端開始比較,借助 key 值找到可復用的節點,再進行相關操作。相比 React 的 diff 算法,同樣情況可以減少移動節點次數,減少不必要的性能損耗
  • Vue3 核心 diff 算法采用了最長遞增子序列


雙端比較算法

  • 使用 舊列表 的頭一個節點 oldStartNode 與 新列表 的頭一個節點 newStartNode 對比
  • 使用 舊列表 的最后一個節點 oldEndNode 與 新列表 的最后一個節點 newEndNode 對比
  • 使用 舊列表 的頭一個節點 oldStartNode 與 新列表 的最后一個節點 newEndNode 對比
  • 使用 舊列表 的最后一個節點 oldEndNode 與 新列表 的頭一個節點 newStartNode 對比

樹 diff 的時間復雜度 O(n^3)

  • 對于舊樹上的點 E 來說,它要和新樹上的所有點比較,復雜度為 O(n)
  • 點 E 在新樹上沒有找到,點 E 會被刪除,然后遍歷新樹上的所有點找到對應點(X)去填空,復雜度增加到 O(n^2)
  • 這樣的操作會在舊樹的每個點進行,最終復雜度為 O(n^3),1000 個節點,要計算 1 億次,算法不可用

優化時間復雜度到 O(n)

  • 只比較同一層級,不跨級比較
  • tag 不相同,則直接刪掉重建,不再深度比較
  • tag key,兩者都相同,則認為是相同節點,不再深度比較

簡述 diff 算法過程

在 Vue 中,主要是 patch()patchVnode() updateChildren 這三個方法來實現 Diff 的

  • 當 Vue 中的響應式數據發生變化時,就會觸發 updateCompoent()
  • updateComponent() 會調用 patch() 方法,在該方法中進行比較,調用 sameVnode 判斷是否為相同節點(判斷 key、tag 等靜態屬性),如果是相同節點的話執行 patchVnode 方法,開始比較節點差異,如果不是相同節點的話,則進行替換操作? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??patch() 接收新舊虛擬 DOM,即 oldVnodevnode
  1. 首先判斷 vnode 是否存在,如果不存在,刪除舊節點
  2. 如果 vnode 存在,再判斷 oldVnode,如果不存在,只需新增整個 vnode 即可
  3. 如果 vnode oldVnode 都存在,判斷兩者是不是相同節點,如果是,調用 patchVnode() ,對兩個節點進行詳細比較
  4. 如果兩者不是相同節點,只需將 vnode 轉換為真實 DOM 替換 oldVnode
  • patchVnode 同樣接收新舊虛擬 DOM,即 oldVnodevnode
  1. 首先判斷兩個虛擬 DOM 是不是全等,即沒有任何變動,是的話直接結束函數,否者繼續執行
  2. 其次更新節點的屬性,接著判斷 vnode.text 是否存在,存在的話只需更新節點文本即可,否則繼續執行
  3. 判斷 vnode oldVnode 是否有孩子節點
    1. 如果兩者都有孩子節點,執行 updateChildren() ,進行比較更新
    2. 如果 vnode 有孩子,oldVnode 沒有,則直接刪除所有孩子節點,并將該文本屬性設為空
    3. 如果 oldVnode 有孩子,vnode 沒有,則直接刪除所有孩子節點
    4. 如果兩者都沒有孩子節點,就判斷 oldVnode.text 是否有內容,有的話情況內容即可
  • updateChildren 接收三個參數:parentElm 父級真實節點、oldCh 為 oldVnode 的孩子節點、newCh 為 Vnode 的孩子節點oldCh 和 newCh 都是一個數組。正常我們想到的方法就是對這兩個數組一一比較,時間復雜度為 O(NM)。Vue 中是通過四個指針實現的
  1. 首先是 oldStartVnode newStartVnode 進行比較(兩頭比較),如果比較相同的話,就可以執行 patchVnode
  2. -如果 oldStartVnode newStartVnode 匹配不上的話,接下來就是 oldEndVnode newEndVnode 做比較了(兩尾比較)
  3. 如果兩頭和兩尾比較都不是相同節點的話,就開始交叉比較,首先是 oldStartVnode newEndVnode 做比較(頭尾比較)
  4. 如果 oldStartVnode 和 newEndVnode 匹配不上的話,就 oldEndVnode newStartVnode 進行比較(尾頭比較)如果這四種比較方法都匹配不到相同節點,才是用暴力解法,針對 newStartVnode 去遍歷 oldCh 中剩余的節點,一一匹配

圖片來源:圖文并茂地來詳細講講Vue Diff算法

?

Vue 為何是異步渲染,$nextTick 何用

  • 因為如果不采用異步更新,那么每次更新數據都會對當前組件進行重新渲染。異步渲染(合并 data 修改),再更新視圖,可以提高渲染性能
class Watcher {update() {if (this.computed) {// ...} else if (this.sync) {// ...} else {// 當數據發生變化時會將watcher放到一個隊列中批量更新queueWatcher(this)}}
}const queue: Array<Watcher> = []
let has: { [key: number]: ?true } = {}
let waiting = false
let flushing = false
// 在派發更新時并不會每次修改都觸發watcher的回調
export function queueWatcher(watcher: Watcher) {const id = watcher.id// has對象保證同一個watcher只添加一次if (has[id] == null) {has[id] = trueif (!flushing) {queue.push(watcher)} else {let i = queue.length - 1while (i > index && queue[i].id > watcher.id) {i--}queue.splice(i + 1, 0, watcher)}// 通過waiting保證nextTick的調用邏輯只有一次if (!waiting) {waiting = true// 調用nextTick方法 批量的進行更新nextTick(flushSchedulerQueue)}}
}function flushSchedulerQueue () {// 1.因為父組件的創建過程是先于子的,所以watcher的創建也是先父后子,執行順序也是先父后子// 2.用戶自定義watcher要優先于渲染watcher執行// 3.如果一個組件在父組件watcher執行期間被銷毀,那么它對應的watcher執行都可以被跳過queue.sort((a, b) => a.id - b.id) // 由小到大
}

  • $nextTick 在 DOM 更新完之后,觸發回調,用于獲得更新后的 DOM
  • $nextTick 方法主要是使用了 宏任務 和 微任務,定義一個異步方法,多次調用 nextTick 會將方法存入隊列中,通過這個異步方法清空當前隊列

Vue 2.4 之前都是使用微任務,但是微任務的優先級過高,有些情況下可能會出現比事件冒泡更快的情況,但如果都是用宏任務,有可能會出現渲染的性能問題

新版,默認使用微任務,但在特殊情況下會使用宏任務,比如:v-on

  • 對于實現宏任務,會先判斷是否能用 setImmediate,不能的話降級為 MessageChannel ,以上都不行的話就是用 setTimeout
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {macroTimerFunc = () => {setImmediate(flushCallbacks)}
} else if (typeof MessageChannel !== 'undefined' &&(isNative(MessageChannel) ||// PhantomJSMessageChannel.toString() === '[object MessageChannelConstructor]')
) {const channel = new MessageChannel()const port = channel.port2channel.port1.onmessage = flushCallbacksmacroTimerFunc = () => {port.postMessage(1)}
} else {macroTimerFunc = () => {setTimeout(flushCallbacks, 0)}
}


Vue 常見性能優化方式

  • 合理使用 v-showv-if
  • 合理使用 computed
  • v-for 時加 key(Vue 會進行復用),以及避免和 v-if 同時使用
  • 自定義事件、DOM 事件及時銷毀
  • 合理使用異步組件、路由懶加載
  • 合理使用 keep-alive(SPA 頁面)
  • data 層級不要太深,不要講所有數據都放在 data 中(會增加 getter setter,收集對應 watcher
  • 使用 vue-loader 在開發環境做模板編譯(預編譯)
  • webpack 層面的優化
  • 前端通用的性能優化,如圖片懶加載、防抖、節流
  • 使用 SSR

釋義參數 vue-template-compiler

render 中的參數釋義

_c = createElement
function installRenderHelpers(target) {target._o = markOncetarget._n = toNumbertarget._s = toStringtarget._l = renderListtarget._t = renderSlottarget._q = looseEqualtarget._i = looseIndexOftarget._m = renderStatictarget._f = resolveFiltertarget._k = checkKeyCodestarget._b = bindObjectPropstarget._v = createTextVNodetarget._e = createEmptyVNodetarget._u = resolveScopedSlotstarget._g = bindObjectListenerstarget._d = bindDynamicKeystarget._p = prependModifier
}

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

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

相關文章

PolarDN MISC做題筆記

cat flag 使用01打開flag.png,發現圖片尾部有padding的數據。D0 CF 11 E0 A1 B1 1A E1為office2007以前版本的文件頭。將其另存為flag.doc,打開發現提示需要密碼。&#xff08;可以注意到&#xff1a;D0CF11E0非常類似DOCFILE&#xff09; 使用john的office2john.py 提取hash …

【操作系統】處理機調度算法

實驗3 處理機管理 一、實驗目的 在多道程序或多任務系統中&#xff0c;系統中同時處于就緒態的進程有若干個&#xff0c;即能運行的進程數遠遠大于處理機個數。為了使系統中的各個進程能有條不紊的運行&#xff0c;必須按照某種調度策略&#xff0c;選擇一個進程占用處理機。…

使用puppeteer完成監聽瀏覽器下載文件并保存到自己本地或服務器上完成上傳功能

需求場景 獲取網站點擊的下載pdf&#xff0c;并把pdf重命名再上傳到COS云上面 技術使用 “puppeteer”: “^19.7.2”, “egg”: “^3.15.0”, // 服務期用egg搭的 文件服務使用COS騰訊云 核心思路 獲取瀏覽器下載事件&#xff0c;并把文件保存到本地 const session awai…

Unity3D 框架如何搭建基于純Lua的U框架與開發模式詳解

前言 Unity3D 是一款非常流行的游戲開發引擎&#xff0c;它支持C#、JavaScript和Boo等多種腳本語言。而Lua語言作為一種輕量級的腳本語言&#xff0c;也在游戲開發中得到了廣泛應用。本文將介紹如何在Unity3D框架中搭建基于純Lua的U框架&#xff0c;并詳細講解其開發模式。 對…

MYSQL--存儲過程操作

一&#xff1a;概念&#xff1a; 存儲過程實際上對標了JAVA當中的方法&#xff0c;兩者是相似的&#xff0c;同時需要注意的一點是&#xff0c;MYSQL僅僅在5.0版本之后才出現這種存儲操作的過程&#xff1b; 優點&#xff1a; 1.存儲過程能夠讓運行的速度變得更加迅速&#xff…

SpringBoot指定外部環境配置

nohup java -Xms256m -Xmx512m -Dfile.encodingUTF-8 -jar /usr/local/xxxx.jar --spring.profiles.activeprod > system.log 2>&1 & --spring.profiles.activeprod修改的是多環境配置中內部application.properties里的spring.profiles.active值 -Dspring.config…

ubuntu 查詢流量使用

在Ubuntu系統中&#xff0c;可以使用nethogs命令來查看每個進程的網絡流量使用情況。這個工具可以顯示每個進程的實時網絡流量&#xff0c;從而可以找出使用流量最多的應用。 首先&#xff0c;你需要安裝nethogs。在終端中輸入以下命令&#xff1a; sudo apt install nethogs…

消息隊列MQ 保證消息不丟失(消息可靠性)

文章目錄 概述RabbitMQ 怎么避免消息丟失&#xff08;可靠傳輸&#xff09;RocketMQ 怎么確保消息不丟失Kafka 怎么保證消息不丟失activeMQ 怎么避免消息丟失MQ 宕機了消息是否會丟失線上服務宕機時&#xff0c;如何保證數據100%不丟失嗎&#xff1f;消息隊列消息持久化 概述 …

思偉老友記 | 攜手并進17年 中泰公司的穩步發展和企業傳承

17年攜手并進 合作共贏 2023年是中泰&#xff08;福建&#xff09;混凝土發展有限公司攜手思偉軟件的第17年。在這關鍵的17年間&#xff0c;我們共同經歷了一個行業的興盛發展&#xff0c;也相互見證了彼此的榮耀成長。中泰從泉州惠安洛陽江邊一個簡單的攪拌站&#xff0c;到如…

h-table(表格列表組件的全封裝)

文章目錄 概要h-table的封裝過程查詢組件封裝 h-highForm結果頁右側工具欄封裝RightToolbar結果頁列表組件h-table結果頁vue頁面使用js文件有需要的請私信博主&#xff0c;還請麻煩給個關注&#xff0c;博主不定期更新組件封裝&#xff0c;或許能夠有所幫助&#xff01;&#x…

如何做代幣分析:以 SOL 幣為例

作者&#xff1a;lesleyfootprint.network 編譯&#xff1a;cicifootprint.network 數據源&#xff1a;Solana Token Dashboard &#xff08;僅包括以太坊數據&#xff09; 在加密貨幣和數字資產領域&#xff0c;代幣分析起著至關重要的作用。代幣分析指的是深入研究與代幣…

springmvc基于springboot 的音樂播放系統 _7sdu8

這就意味著音樂播放系統的設計可以比其他系統更為出色的能力&#xff0c;可以更高效的完成最新的ymj排行榜、ymj音樂資訊等功能。 此系統設計主要采用的是JAVA語言來進行開發&#xff0c;JSP技術、采用SSM框架技術&#xff0c;框架分為三層&#xff0c;分別是控制層Controller&…

Seata的 TCC 模式

目錄 概述 使用 依賴與配置 代碼 概述 TCC 模式是一種侵入式的分布式事務解決方案&#xff0c;它不依賴于數據庫的事務&#xff0c;而是要求開發者自定義完成 預提交、提交、回滾的方法邏輯。因此&#xff0c;它是一個種偏 復雜、靈活、有侵入性 的分布式事務處理方案。 De…

針對Umi、React中遇到的 “xxxx”不能用作 JSX 組件 問題解決方案

一、處理方案 這是因為"types/react"、"types/react-dom"在子依賴中使用的版本不一致導致&#xff0c;一般情況npm會自動幫我們處理版本不一致的問題。如果npm處理不了&#xff0c;就需要我們自己手動處理在package.json中添加一項配置 {name:"test&…

Zookeeper選舉Leader源碼剖析

Zookeeper選舉Leader源碼剖析 leader選舉流程 參數說明 myid: 節點的唯一標識&#xff0c;手動設置zxid: 當前節點中最大(新)的事務idepoch-logic-clock: 同一輪投票過程中的邏輯時鐘值相同&#xff0c;每投完一次值會增加 leader選舉流程 默認投票給自己&#xff0c;優先選擇…

vue3 vuex

目錄 Vuex 是什么 什么是“狀態管理模式”&#xff1f; 什么情況下我應該使用 Vuex&#xff1f; 使用方法&#xff1a; 提交載荷&#xff08;Payload&#xff09; 對象風格的提交方式 使用常量替代 Mutation 事件類型 Mutation 必須是同步函數 在組件中提交 Mutation …

redis GEO 類型原理及命令詳解

目錄 前言 一、GeoHash 的編碼方法 二、Redis 操作GEO類型 前言 我們有一個需求是用戶搜索附近的店鋪&#xff0c;就是所謂的位置信息服務&#xff08;Location-Based Service&#xff0c;LBS&#xff09;的應用。這樣的相關服務我們每天都在接觸&#xff0c;用滴滴打車&am…

使用ENV工具編譯RT-Thread【詳細過程講解:從下載到編譯、設置】

感興趣的寶子&#xff0c;可以點個贊收藏&#xff0c;便于后期有需要的時候能快速找到~~ ENV編譯編譯RT-Thread工程的詳細過程講解 ENV簡介ENV的下載設置ENV使用ENV編譯RT-Thread工程◆ 打開ENV◆ 輸入打包命令◆ 查看并打開工程文件◆ 使用menuconfig 對生成項目的RT-Thread配…

【Git企業實戰開發】Git常用開發流操作總結

【Git企業實戰開發】Git常用開發流操作總結 大家好 我是寸鐵&#x1f44a; 總結了一篇Git常用開發流操作總結的文章? 喜歡的小伙伴可以點點關注 &#x1f49d; 現在剛做項目的伙伴&#xff0c;可能你之前學過git&#xff0c;但是一實戰發現不熟悉 沒關系&#xff0c;看寸鐵這篇…

fastadmin引用 redis 方法2

頁面上引用 use \think\cache\driver\Redis; $redis new Redis();$redis->set(key, value);// 獲取鍵值對的值$value $redis->get(key);echo $value;如果執行后出現 不支持redis&#xff0c; 檢查系統是否開啟 redis 擴展。 如果是小皮系統。 項目-管理-php擴展&#x…