Tiptap(以及許多其他基于ProseMirror 的文本編輯器)有這個驚人的 API,我們可以在其中鏈接命令。
對于例如:
editor.chain().focus().toggleItalic().run()
在這里,呼叫會chain()回傳所有可鏈接的命令,這些命令本身會回傳可鏈接的命令,這就是鏈一直持續下去的方式,直到您呼叫run().
呼叫后run(),之間的命令chain()和run()同步執行。
有趣的是(據我所知)這不是一門課。所有這些也可以通過為 Tiptap 創建自定義擴展來擴展(包括打字)。請參閱此粗體擴展及其型別。
我確實去過那里的來源,但無法理解太多。
我真的很喜歡這種設計模式,并且想知道我應該如何去實作它……
說,我想在這個模式上實作一個計算器。我怎樣才能使這條線作業?
calculator.chain().setValue(10).add(3).sub(12).run() // 1
謝謝!
uj5u.com熱心網友回復:
有很多方法可以實作這一點,這里只是一個簡單的物件。類封裝可能是一個好主意。只要您將方法包含在單個物件中,您就可以繼續回傳它并添加到回呼佇列中,最終將執行.run()并中斷回圈。
const calculator = {
state: { value: 0 },
callbacks: [] as ((...args: any[]) => any)[],
_exec: {
setValue: (val: number) => (calculator.state.value = val),
add: (val: number) => (calculator.state.value = val),
sub: (val: number) => (calculator.state.value -= val),
},
_queue: {
setValue: (val: number) => {
calculator.callbacks.push(() => calculator._exec.setValue(val));
return calculator._queue;
},
add: (val: number) => {
calculator.callbacks.push(() => calculator._exec.add(val));
return calculator._queue;
},
sub: (val: number) => {
calculator.callbacks.push(() => calculator._exec.sub(val));
return calculator._queue;
},
run: () => {
calculator.callbacks.forEach((cb) => cb());
calculator.callbacks = [];
},
},
chain: () => calculator._queue,
};
calculator.chain().setValue(10).add(3).sub(12).run();
console.log(calculator.state.value); // logs 1
uj5u.com熱心網友回復:
只需使用class:
class Calculator {
constructor(value) {
this.value = value;
}
run() { return this.value; }
add(x) { return new Calculator(this.value x); }
sub(x) { return new Calculator(this.value - x); }
log() { console.log(this.value); return this; }
static withValue(v) { return new this(v); }
}
const calc = Calculator.withValue(10).add(3).log();
console.log(calc.sub(12).run());
console.log(calc.add(29).run());
對于方法鏈接來說,唯一重要的是Calculator從每個可鏈接的方法回傳一個包含所有方法的物件(這里:一個實體)。您也可以在沒有class語法的情況下實作相同的目的:
function calculatorWithValue(v) {
return {
run() { return v; },
add(x) { return calculatorWithValue(v x); },
sub(x) { return calculatorWithValue(v - x); },
log() { console.log(v); return this; },
};
}
const calc = calculatorWithValue(10).add(3).log();
console.log(calc.sub(12).run());
console.log(calc.add(29).run());
我建議保持物件不可變,以允許創建多個獨立鏈或分叉現有鏈 - 請參閱上面的示例,其中第二個結果是10 3 29, not 10 3 - 12 29。
如果你想讓執行變得懶惰,那也很容易:
class Calculator {
constructor(run) {
this.run = run;
}
static withValue(v) { return new this(() => v); }
add(x) { return new Calculator(() => this.run() x); }
sub(x) { return new Calculator(() => this.run() - x); }
log() { return new Calculator(() => {
const v = this.run();
console.log(v);
return v;
}); }
}
const calc = Calculator.withValue(10).add(3).log();
console.log(calc.sub(12).run());
console.log(calc.add(29).run());
如果您想通過某種插件架構使其可擴展,只需在原型上放置更多方法,或動態構建物件。對于 TypeScript,您將使用宣告合并來使用Calculator插件提供的簽名來修改介面。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/407288.html
標籤:
