使用Hook构建解耦的Vue.js应用程序
背景介绍
- 表单提交时,业务要求对数据埋点以便作数据分析用,对于开发人员来说,实现的方式有多种:
- 业务代码和埋点相关的代码直接混在一起,这是最直接的实现方式,但也会带来一些问题,埋点代码分散在项目的各地方不利于维护,与业务代码混淆不利于阅读。
- 分离业务代码和埋点代码,保持两者的独立性,能解决方案1中的问题,但是会导致代码层面复杂些
代码实现
- hook.js
const hooks = []
export function addHook (hook) {
hooks.push(hook)
}
export function runHooks (context) {
return hooks.filter(hook => hook.condition(context))
.map(hook => hook.callback(context))
}
export function withHooks (func, context) {
return (...args) => {
console.log(args)
const result = func(...args)
if (result.then) {
result
.then(payload => runHooks({ ...context, payload }))
.catch(error => runHooks({ ...context, error }))
return result
}
runHooks({ ...context, payload: result })
return result
}
}
复制代码
- 上面的代码可以将Hook对象添加到一个Hooks堆栈中,一旦调用runHooks()就会触发它们。每个Hook都是一个具有条件和回调的对象。仅当condition()函数返
- tracking.js
import { addHook } from '@/utils/hooks'
const CONTACT_FORM = 'contact-form.post'
addHook({
condition ({ error, id }) {
return !error && id === CONTACT_FORM
},
callback (context) {
// 用于数据报送、或数据分析的逻辑
console.log('用于数据报送、或数据分析的逻辑', context)
}
})
复制代码
-
可以看到我们添加了一个新的Hook,只有在没有错误并且id context参数与CONTACT_FORM id匹配时才会触发。在callback()函数中,我们通常会在我们选择的跟踪服务中触发一个事件,但因为这只是一个演示,我们只需触发一个console.log()
-
模拟后台请求 loanApply.js
export function post (data) {
return Promise.resolve(data)
}
复制代码
- 组件中使用
<template>
<form @submit.prevent="submit">
<label class="contact-form-label">
Name
<input v-model="data.name">
</label>
<label class="contact-form-label">
Message
<textarea v-model="data.message"/>
</label>
<button>Submit</button>
</form>
</template>
<script>
import './tracking'
import { post } from '@/api/loanApply'
import { withHooks } from '@/utils/hooks'
export default {
data () {
return { data: { name: '', message: '' } }
},
methods: {
submit () {
withHooks(this.test, { id: 'contact-form.post' })(this.data)
},
async test (param) {
const {message, name} = await post(param)
console.log(message, name, '处理表单本身的业务逻辑')
return param
}
}
}
</script>
复制代码
总结
- 与编程中的其他的高级模式一样,hook也有其缺点。首先,它们增加了另一层复杂性。将跟踪逻辑直接添加到组件的代码中虽然不是最干净的解决方案,但它绝对是最直接的。特别是如果您的应用程序非常小,使用Hooks可能只会使您的代码库更复杂,而不是简化它。
- 因此决定是否要实现此模式之前首先考虑所有优点和缺点。在合适的情况下。