Skip to content

Commit 3d74a20

Browse files
committed
feat: 完善组件功能
1 parent 1a1f82b commit 3d74a20

3 files changed

Lines changed: 311 additions & 17 deletions

File tree

src/components/BootstrapBlazor.Vditor/Vditor.razor.cs

Lines changed: 281 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace BootstrapBlazor.Components;
88

99
/// <summary>
10-
/// Vditor component
10+
/// Vditor markdown component
1111
/// </summary>
1212
public partial class Vditor
1313
{
@@ -17,11 +17,54 @@ public partial class Vditor
1717
[Parameter]
1818
public VditorOptions? Options { get; set; }
1919

20+
/// <summary>
21+
/// 获得/设置 组件渲染完毕回调方法 默认 null
22+
/// </summary>
23+
[Parameter]
24+
public Func<Task>? OnRenderedAsync { get; set; }
25+
26+
/// <summary>
27+
/// 获得/设置 组件输入时回调方法 高频触发 默认 null
28+
/// </summary>
29+
[Parameter]
30+
public Func<string, Task>? OnInputAsync { get; set; }
31+
32+
/// <summary>
33+
/// 获得/设置 组件获得焦点时回调方法 默认 null
34+
/// </summary>
35+
[Parameter]
36+
public Func<string, Task>? OnFocusAsync { get; set; }
37+
38+
/// <summary>
39+
/// 获得/设置 组件失去焦点时回调方法 默认 null
40+
/// </summary>
41+
[Parameter]
42+
public Func<string, Task>? OnBlurAsync { get; set; }
43+
44+
/// <summary>
45+
/// 获得/设置 组件选择内容时回调方法 默认 null
46+
/// </summary>
47+
[Parameter]
48+
public Func<string, Task>? OnSelectAsync { get; set; }
49+
50+
/// <summary>
51+
/// 获得/设置 组件按 ESC 案件时回调方法 默认 null
52+
/// </summary>
53+
[Parameter]
54+
public Func<string, Task>? OnEscapeAsync { get; set; }
55+
56+
/// <summary>
57+
/// 获得/设置 组件按 Ctrl + Enter 组合案件时回调方法 默认 null
58+
/// </summary>
59+
[Parameter]
60+
public Func<string, Task>? OnCtrlEnterAsync { get; set; }
61+
2062
private string? ClassString => CssBuilder.Default("bb-vditor")
2163
.AddClassFromAttributes(AdditionalAttributes)
2264
.Build();
2365

2466
private string? _lastValue;
67+
private IJSObjectReference? _vditor;
2568

2669
/// <summary>
2770
/// <inheritdoc/>
@@ -41,31 +84,258 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
4184
if (_lastValue != Value)
4285
{
4386
_lastValue = Value;
44-
await InvokeVoidAsync("update", Id, Value);
87+
if (_vditor != null)
88+
{
89+
await _vditor.InvokeVoidAsync("setValue", Value, true);
90+
}
4591
}
4692
}
4793

4894
/// <summary>
4995
/// <inheritdoc/>
5096
/// </summary>
5197
/// <returns></returns>
52-
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new
98+
protected override async Task InvokeInitAsync()
99+
{
100+
_vditor = await InvokeAsync<IJSObjectReference>("init", Id, Interop, new
101+
{
102+
Options,
103+
Value
104+
});
105+
}
106+
107+
/// <summary>
108+
/// 重新设置编辑器方法
109+
/// </summary>
110+
/// <param name="value"></param>
111+
/// <param name="options"></param>
112+
/// <returns></returns>
113+
public async Task Reset(string value, VditorOptions options)
114+
{
115+
if (!string.IsNullOrEmpty(value))
116+
{
117+
Value = value;
118+
}
119+
_vditor = await InvokeAsync<IJSObjectReference>("reset", Id, Value, Options);
120+
}
121+
122+
/// <summary>
123+
/// 在焦点处插入内容,并默认进行 Markdown 渲染
124+
/// </summary>
125+
/// <param name="value">要插入的 markdown 值</param>
126+
/// <param name="render">是否渲染</param>
127+
public async ValueTask InsertValueAsync(string? value, bool render = true)
53128
{
54-
Options,
55-
Value,
56-
TriggerUpdateValueAsync = nameof(TriggerUpdateValueAsync)
57-
});
129+
if (_vditor != null)
130+
{
131+
await _vditor.InvokeVoidAsync("insertValue", Id, value, render);
132+
}
133+
}
134+
135+
/// <summary>
136+
/// 获取编辑器的 markdown 内容
137+
/// </summary>
138+
public async ValueTask<string?> GetValueAsync()
139+
{
140+
string? ret = null;
141+
if (_vditor != null)
142+
{
143+
ret = await _vditor.InvokeAsync<string?>("getValue");
144+
}
145+
return ret;
146+
}
147+
148+
/// <summary>
149+
/// 获取 markdown 渲染后的 HTML
150+
/// </summary>
151+
public async ValueTask<string?> GetHtmlAsync()
152+
{
153+
string? ret = null;
154+
if (_vditor != null)
155+
{
156+
ret = await _vditor.InvokeAsync<string?>("getHTML");
157+
}
158+
return ret;
159+
}
160+
161+
/// <summary>
162+
/// 返回选中的字符串
163+
/// </summary>
164+
public async ValueTask<string?> GetSelectAsync()
165+
{
166+
string? ret = null;
167+
if (_vditor != null)
168+
{
169+
ret = await _vditor.InvokeAsync<string?>("getSelection");
170+
}
171+
return ret;
172+
}
173+
174+
/// <summary>
175+
/// 解除编辑器禁用
176+
/// </summary>
177+
public async ValueTask EnableAsync()
178+
{
179+
if (_vditor != null)
180+
{
181+
await _vditor.InvokeVoidAsync("enable");
182+
}
183+
}
184+
185+
/// <summary>
186+
/// 禁用编辑器
187+
/// </summary>
188+
public async ValueTask DisableAsync()
189+
{
190+
if (_vditor != null)
191+
{
192+
await _vditor.InvokeVoidAsync("disable");
193+
}
194+
}
195+
196+
/// <summary>
197+
/// 聚焦编辑器
198+
/// </summary>
199+
public async ValueTask FocusAsync()
200+
{
201+
if (_vditor != null)
202+
{
203+
await _vditor.InvokeVoidAsync("focus");
204+
}
205+
}
206+
207+
/// <summary>
208+
/// 让编辑器失去焦点
209+
/// </summary>
210+
public async ValueTask BlurAsync()
211+
{
212+
if (_vditor != null)
213+
{
214+
await _vditor.InvokeAsync<string?>("blur");
215+
}
216+
}
217+
218+
/// <summary>
219+
/// 客户端渲染完毕回调方法由 JavaScript 调用
220+
/// </summary>
221+
/// <returns></returns>
222+
[JSInvokable]
223+
public async Task TriggerRenderedAsync()
224+
{
225+
if (OnRenderedAsync != null)
226+
{
227+
await OnRenderedAsync();
228+
}
229+
}
230+
231+
/// <summary>
232+
/// 组件录入时回调方法由 JavaScript 调用
233+
/// </summary>
234+
/// <param name="value"></param>
235+
/// <returns></returns>
236+
[JSInvokable]
237+
public async Task TriggerInputAsync(string value)
238+
{
239+
if (OnInputAsync != null)
240+
{
241+
_lastValue = value;
242+
CurrentValue = value;
243+
await OnInputAsync(value);
244+
}
245+
}
58246

59247
/// <summary>
60248
/// 触发 Value 值改变回调方法由 JavaScript 调用
61249
/// </summary>
62250
/// <param name="value"></param>
63251
/// <returns></returns>
64252
[JSInvokable]
65-
public Task TriggerUpdateValueAsync(string value)
253+
public async Task TriggerFocusAsync(string value)
66254
{
67-
CurrentValue = value;
68-
return Task.CompletedTask;
255+
if (OnFocusAsync != null)
256+
{
257+
await OnFocusAsync(value);
258+
}
69259
}
70-
}
71260

261+
/// <summary>
262+
/// 触发 Value 值改变回调方法由 JavaScript 调用
263+
/// </summary>
264+
/// <param name="value"></param>
265+
/// <returns></returns>
266+
[JSInvokable]
267+
public async Task TriggerBlurAsync(string value)
268+
{
269+
if (OnBlurAsync != null)
270+
{
271+
_lastValue = value;
272+
CurrentValue = value;
273+
await OnBlurAsync(value);
274+
}
275+
}
276+
277+
/// <summary>
278+
/// 触发 Value 值改变回调方法由 JavaScript 调用
279+
/// </summary>
280+
/// <param name="value"></param>
281+
/// <returns></returns>
282+
[JSInvokable]
283+
public async Task TriggerSelectAsync(string value)
284+
{
285+
if (OnSelectAsync != null)
286+
{
287+
await OnSelectAsync(value);
288+
}
289+
}
290+
291+
/// <summary>
292+
/// 触发 Value 值改变回调方法由 JavaScript 调用
293+
/// </summary>
294+
/// <param name="value"></param>
295+
/// <returns></returns>
296+
[JSInvokable]
297+
public async Task TriggerEscapeAsync(string value)
298+
{
299+
if (OnEscapeAsync != null)
300+
{
301+
_lastValue = value;
302+
CurrentValue = value;
303+
await OnEscapeAsync(value);
304+
}
305+
}
306+
307+
/// <summary>
308+
/// 触发 Value 值改变回调方法由 JavaScript 调用
309+
/// </summary>
310+
/// <param name="value"></param>
311+
/// <returns></returns>
312+
[JSInvokable]
313+
public async Task TriggerCtrlEnterAsync(string value)
314+
{
315+
if (OnCtrlEnterAsync != null)
316+
{
317+
_lastValue = value;
318+
CurrentValue = value;
319+
await OnCtrlEnterAsync(value);
320+
}
321+
}
322+
323+
/// <summary>
324+
/// <inheritdoc/>
325+
/// </summary>
326+
/// <param name="disposing"></param>
327+
/// <returns></returns>
328+
protected override async ValueTask DisposeAsync(bool disposing)
329+
{
330+
if (disposing)
331+
{
332+
if (_vditor != null)
333+
{
334+
await _vditor.DisposeAsync();
335+
_vditor = null;
336+
}
337+
338+
await base.DisposeAsync(disposing);
339+
}
340+
}
341+
}

src/components/BootstrapBlazor.Vditor/Vditor.razor.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,43 @@ export async function init(id, invoke, options) {
1111
await addScript('./_content/BootstrapBlazor.Vditor/js/vditor.js');
1212

1313
const { options: op, value } = options;
14-
const vditor = new Vditor(id, getOptions({ ...op, value }));
14+
const vditor = new Vditor(id, getOptions(invoke, { ...op, value }));
1515

1616
Data.set(id, { el, invoke, vditor });
17+
return vditor;
1718
}
1819

19-
const getOptions = options => {
20+
const getOptions = (invoke, options) => {
2021
return {
2122
cache: {
2223
enable: false,
2324
},
24-
...options
25+
...options,
26+
after: () => invoke.invokeMethodAsync('TriggerRenderedAsync'),
27+
input: value => invoke.invokeMethodAsync('TriggerInputAsync', value),
28+
focus: value => invoke.invokeMethodAsync('TriggerFocusAsync', value),
29+
blur: value => invoke.invokeMethodAsync('TriggerBlurAsync', value),
30+
esc: value => invoke.invokeMethodAsync('TriggerEscapeAsync', value),
31+
select: value => invoke.invokeMethodAsync('TriggerSelectAsync', value),
32+
ctrlEnter: value => invoke.invokeMethodAsync('TriggerCtrlEnterAsync', value)
2533
};
2634
}
2735

28-
export async function update(id, value) {
36+
export async function reset(id, value, options) {
37+
const md = Data.get(id);
38+
const { invoke, vditor } = md;
39+
if (vditor) {
40+
vditor.destroy();
2941

42+
md.vditor = new Vditor(id, getOptions(invoke, { ...options, value }));
43+
}
44+
return md.vditor;
3045
}
3146

3247
export function dispose(id) {
33-
48+
const md = Data.get(id);
49+
const { vditor } = md;
50+
if (vditor) {
51+
vditor.destroy();
52+
}
3453
}

src/components/BootstrapBlazor.Vditor/VditorOptions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ namespace BootstrapBlazor.Components;
55
/// <summary>
66
/// Vditor 配置类
77
/// </summary>
8-
public class VditorOptions
8+
public struct VditorOptions
99
{
10+
/// <summary>
11+
/// 构造函数
12+
/// </summary>
13+
public VditorOptions() { }
14+
1015
/// <summary>
1116
/// 获得/设置 编辑器模式。默认 <see cref="VditorMode.IR"/>
1217
/// </summary>

0 commit comments

Comments
 (0)