本項目是基於vue2.x + vue-compostion-api基礎上,可能出在過分封裝,可是文章目的在於思考若是在vue 3.0更好地複用和組合組件邏輯.javascript
vue2.x的組件是基於選項的, 好比method必須寫在methods對象裏面,反觀vue3.0是基於函數的,不存在上述的制約.可是基於函數太過於自由,會致使咱們寫出麪條代碼,setup 函數會變的原來越大,最終組件愈來愈難維護.html
界面一共有兩個輸入框,分別是frist-name,last-name和一個div 顯示nickname,每次鼠標失去焦點會更新nickname(fristName + lastName).vue
`<div class="home">java
<form> <input id="first-name" placeholder="frist name" @blur="onFirstName" /> <br/><br/> <input id="last-name" placeholder="last name" @blur="onLasttName" /> <br/> nickname: {{nickname}} </form>
</div>`react
由於要從steup函數抽離重複的邏輯, state在onblur事件中脫離上下文,因此要建立build 函數給函數增長預設參數.api
function bind(fn: any, ...restArgs: any[]) { const args = new Array(restArgs.length); for (let i = 0; i < args.length; i++) { args[i] = restArgs[i]; } return fn.bind(null, ...args); }
import { defineComponent, reactive, toRefs } from '@vue/composition-api'; // code from hleper.ts function bind(fn: any, ...restArgs: any[]) { const args = new Array(restArgs.length); for (let i = 0; i < args.length; i++) { args[i] = restArgs[i]; } return fn.bind(null, ...args); } type State = { fristName: string; lastName: string; nickname: string; // firstname + last name } interface OnBlurHandle { (state: State, value: string): void; } const composeNickName = (state: State) => { state.nickname = `YJ ${state.fristName} ${state.lastName}`; } const validation = (value: string) => { // todo... } const onBlur = (state: State, fn: OnBlurHandle, event: Event) => { const value = (event.target as any).value; // other logic validation(value); composeNickName(state); fn(state, value) } const onFirstName = (state: State, value: string) => { state.fristName = value; } const onLasttName = (state: State, value: string) => { state.lastName = value; } export default defineComponent({ setup() { const state = reactive<State>({ fristName: "", lastName: "", nickname: '' // firstname + last name }); return { onFirstName: bind(onBlur, state, onFirstName), onLasttName: bind(onBlur, state, onLasttName), ...toRefs(state) } } })