一、Vue3 h函數通信
Vue3 h函數是Vue3提供的一個函數式編程方式,可以使用它來創建Vue組件的虛擬節點(vnode),還可以在組件中更新數據。與Vue2的createElement函數相比,Vue3 h函數是一個更輕量,更易用的函數。h函數通常與Vue3的渲染函數(render)一起使用,在函數式編程中具有非常重要的作用。
h函數是一種虛擬節點的創建方式,在Vue3中,組件之間通信可以使用props和$emit方法,其他組件的數據可以通過props傳遞進來,當前組件的數據可以通過$emit方法向外發送。虛擬節點和h函數允許我們在組件之間直接通信,而不是通過props和$emit方法進行傳遞,提高了組件之間通信的效率。
我們來看一個簡單的例子:
const App = {
data() {
return {
count: 0
}
},
render() {
return h('div', {}, [
h('h1', {}, '當前的計數器值是:' + this.count),
h('button', {
onClick: () => {
this.count++
}
}, '加一')
])
}
}
createApp(App).mount('#app')
在上述代碼中,我們通過Vue3 h函數創建了一個div元素,h函數的第一個參數是元素名稱,第二個參數是一個對象,其中可以傳遞元素的屬性,第三個參數是數組,其中可以傳遞虛擬節點。在數組中,我們傳遞了一個h函數創建的h1元素和一個button元素,button元素上可以通過onClick方法進行綁定事件,用來觸發count值的自增。
二、Vue3 h函數和createVNode
可以使用createVNode函數來創建單個的虛擬節點,也可以使用h函數創建一個虛擬節點的樹形結構。createVNode一個的參數可以是一個標籤字符串,或是一個組件對象。它的第二個參數是一個對象,可以傳遞元素的屬性,第三個參數是一個數組,用於傳遞子元素。createVNode和h函數的最大區別在於createVNode使用對象的方式來創建虛擬節點,而h函數使用函數的方式來進行創建。
接下來,我們通過一個展示列表的例子,來比對createVNode函數和h函數的不同:
const App = {
data() {
return {
list: [
{
name: '張三',
age: 20
},
{
name: '李四',
age: 22
},
{
name: '王五',
age: 24
}
]
}
},
render() {
const listItems = this.list.map(item => {
return createVNode('li', {
key: item.name
}, [
createVNode('span', {}, item.name),
createVNode('span', {}, item.age)
])
})
return createVNode('ul', {}, listItems)
}
}
createApp(App).mount('#app')
上述代碼中,我們首先通過createVNode函數創建li元素,並傳遞了元素的屬性和子元素,然後通過map函數遍歷了name和age,得到一個li元素的數組,最後再通過createVNode函數創建ul元素,並傳遞了子元素為li數組。createVNode函數的使用方式和createElement函數類似,但是我們可以看到使用方式更為簡潔。
接下來,我們使用h函數來創建同樣的列表:
const App = {
data() {
return {
list: [
{
name: '張三',
age: 20
},
{
name: '李四',
age: 22
},
{
name: '王五',
age: 24
}
]
}
},
render() {
const listItems = this.list.map(item => {
return h('li', {
key: item.name
}, [
h('span', {}, item.name),
h('span', {}, item.age)
])
})
return h('ul', {}, listItems)
}
}
createApp(App).mount('#app')
通過對比可以看到,createVNode函數和h函數都可以用來創建虛擬節點,但是它們的使用方式是不同的。createVNode函數的使用方式更加簡潔明了,h函數的使用方式則更加函數式,區別在於我們對於節點的描述方式有所不同。我們需要根據實際情況來選擇使用哪種方式。
三、Vue3 h函數源碼
Vue3的源碼是通過TypeScript編寫的,h函數的定義方式如下:
import { createVNode } from './vnode'
export function h(type, propsOrChildren, children) {
const l = arguments.length
if (l === 2) {
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
if (isVNode(propsOrChildren)) {
return createVNode(type, null, [propsOrChildren])
}
return createVNode(type, propsOrChildren)
}
return createVNode(type, null, propsOrChildren)
} else {
if (l === 3 && isVNode(children)) {
if (isArray(children)) {
children.unshift(propsOrChildren)
} else {
children = [propsOrChildren, children]
}
} else if (isNumber(children) || isString(children)) {
children = [children]
}
return createVNode(type, propsOrChildren, children)
}
}
從源碼中我們可以看到,h函數的參數是不固定的,可以接受1到3個參數。如果只傳遞了兩個參數,那麼第二個參數如果是一個對象,則代表元素的屬性信息,如果是一個數組,則代表元素的子節點信息。第三個參數則代表元素的子節點信息。由於在h函數中,我們將props和children參數都傳遞給了createVNode函數,因此在使用h函數創建虛擬節點時,createVNode函數會提供更多參數的選項。
四、Vuex函數和Vue3函數式
Vue3的函數式編程提供了新的方式來共享組件狀態和邏輯。Vue3中的一個設計重心是讓狀態管理更加流暢和自然,因此在引入Vuex之後,Vue3也提供了一個函數式API,用於管理共享狀態。
下面是使用Vue3函數式API的代碼示例:
import { provide, reactive, computed, inject } from 'vue' const storeSymbol = Symbol()
function useProvideStore() {
const state = reactive({
count: 0
})
const getters = computed(() => {
return {
doubleCount: state.count * 2
}
})
const mutations = {
increment(state) {
state.count++
}
}
provide(storeSymbol, {
state,
getters,
mutations
})
}
function useInjectStore() {
const store = inject(storeSymbol)
function increment() {
store.mutations.increment(store.state)
}
return {
state: store.state,
getters: store.getters,
increment
}
}
// 使用useProvideStore和useInjectStore方法,在父組件中共享狀態
const parentComponent = {
setup() {
useProvideStore()
return {}
},
template: `
`,
components: {
ChildComponent
}
}
const ChildComponent = {
setup() {
const { state, getters, increment } = useInjectStore()
return {
count: state.count,
doubleCount: getters.doubleCount,
increment
}
},
template: `
當前計數器值:{{count}}
當前計數器的雙倍值:{{doubleCount}}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/180079.html