当前位置: 首页 > news >正文

巧家县住房和城乡建设局网站揭阳网站建设工作

巧家县住房和城乡建设局网站,揭阳网站建设工作,惠州房地产网站开发,一个网站做多有几种颜色文章目录 获取资源从源码构建从CDN获取获取扩展插件 创建项目创建控件创建Blazor组件初始化保存销毁编写渲染逻辑 实现只读/编辑功能切换模式获取只读模式状态响应切换事件 实现明/暗主题切换项目地址 Editor.js 是一个基于 Web 的所见即所得富文本编辑器#xff0c;它由CodeX… 文章目录 获取资源从源码构建从CDN获取获取扩展插件 创建项目创建控件创建Blazor组件初始化保存销毁编写渲染逻辑 实现只读/编辑功能切换模式获取只读模式状态响应切换事件 实现明/暗主题切换项目地址 Editor.js 是一个基于 Web 的所见即所得富文本编辑器它由CodeX团队开发。之前写过一篇博文专门介绍过这个编辑器可以回看 开源好用的所见即所得(WYSIWYG)编辑器Editor.js。 .NET MAUI Blazor允许使用 Web UI 生成跨平台本机应用。 组件在 .NET 进程中以本机方式运行并使用本地互操作通道将 Web UI 呈现到嵌入式 Web 视图控件BlazorWebView。 这次我们将Editor.js集成到.NET MAUI应用中。并实现只读切换明/暗主题切换等功能。 使用.NET MAUI实现跨平台支持本项目可运行于Android、iOS平台。 获取资源 我们先要获取web应用的资源文件jscss等以便MAUI的视图呈现标准的Web UI。有两种方式可以获取 从源码构建从CDN获取 从源码构建 此方法需要首先安装nodejs 克隆Editorjs项目到本地 git clone https://github.com/codex-team/editor.js.git运行 npm i以及 npm run build等待nodejs构建完成在项目根目录找到dist/editorjs.umd.js这个就是我们需要的js文件 从CDN获取 从官方CDN获取 https://cdn.jsdelivr.net/npm/editorjs/editorjslatest获取扩展插件 Editor.js中的每个块都由插件提供。有简单的外部脚本有自己的逻辑。默认Editor.js项目中已包含唯一的 Paragraph 块。其它的工具插件可以单独获取。 同样我们可以找到这些插件的源码编译或通过CDN获取 Header链接HTML块简单图片无后端要求图片清单列表嵌入引用 创建项目 新建.NET MAUI Blazor项目命名Editorjs 将editorjs.umd.js和各插件js文件拷贝至项目根目录下wwwroot文件夹文件结构如下 在wwwroot创建editorjs_index.html文件并在body中引入editorjs.umd.js和各插件js文件 body...script srclib/editorjs/editorjs.umd.js/scriptscript srclib/editorjs/tools/checklistlatest.js/scriptscript srclib/editorjs/tools/codelatest.js/scriptscript srclib/editorjs/tools/delimiterlatest.js/scriptscript srclib/editorjs/tools/embedlatest.js/scriptscript srclib/editorjs/tools/headerlatest.js/scriptscript srclib/editorjs/tools/imagelatest.js/scriptscript srclib/editorjs/tools/inline-codelatest.js/scriptscript srclib/editorjs/tools/linklatest.js/scriptscript srclib/editorjs/tools/nested-listlatest.js/scriptscript srclib/editorjs/tools/markerlatest.js/scriptscript srclib/editorjs/tools/quotelatest.js/scriptscript srclib/editorjs/tools/tablelatest.js/script /body创建控件 创建 EditNotePage.xaml EditNotePage类作为视图控件继承于ContentViewEditNotePage.xaml的完整代码如下 ContentView xmlnshttp://schemas.microsoft.com/dotnet/2021/mauixmlns:xhttp://schemas.microsoft.com/winfx/2009/xamlxmlns:matoclr-namespace:Editorjs;assemblyEditorjsxmlns:serviceclr-namespace:Editorjs.ViewModels;assemblyEditorjsxmlns:xcthttp://schemas.microsoft.com/dotnet/2022/maui/toolkitx:NameMainPagex:ClassEditorjs.Controls.EditNotePageGrid BackgroundColor{AppThemeBinding Light{StaticResource LightPageBackgroundColor}, Dark{StaticResource DarkPageBackgroundColor}}RowDefinitionsAuto, *, AutoPadding20, 10, 20, 0Grid Grid.Row0Margin0, 0, 0, 10Grid.ColumnDefinitionsColumnDefinition Widthauto/ColumnDefinitionColumnDefinition/ColumnDefinitionColumnDefinition/ColumnDefinition/Grid.ColumnDefinitionsEntry Grid.Column1Placeholder请输入标题Margin10, 0, 0, 0VerticalOptionsCenterText{Binding Title} /EntryHorizontalStackLayout Grid.Column2HeightRequest60VerticalOptionsCenterHorizontalOptionsEndMargin0, 0, 10, 0StackLayout RadioButtonGroup.GroupNameStateRadioButtonGroup.SelectedValue{Binding NoteSegmentState,ModeTwoWay}OrientationHorizontalRadioButton Value{x:Static service:NoteSegmentState.Edit}Content编辑/RadioButtonRadioButton Value{x:Static service:NoteSegmentState.PreView}Content预览/RadioButton/StackLayout/HorizontalStackLayout/GridBlazorWebView Grid.Row1Margin-10, 0x:NamemainMapBlazorWebViewHostPagewwwroot/editorjs_index.htmlBlazorWebView.RootComponentsRootComponent Selector#appx:NamerootComponentComponentType{x:Type mato:EditorjsPage} //BlazorWebView.RootComponents/BlazorWebViewActivityIndicator Grid.RowSpan4IsRunning{Binding Loading}/ActivityIndicator/Grid /ContentView 创建一个EditNotePageViewModel的ViewModel类用于处理页面逻辑。代码如下 public class EditNotePageViewModel : ObservableObject, IEditorViewModel {public FuncTaskstring OnSubmitting { get; set; }public Actionstring OnInited { get; set; }public Action OnFocus { get; set; }public EditNotePageViewModel(){Submit new Command(SubmitAction);NoteSegmentStateNoteSegmentState.Edit;var content ;using (Stream stream Assembly.GetExecutingAssembly().GetManifestResourceStream(Editorjs.Assets.sample1.json)){if (stream ! null){using (StreamReader reader new StreamReader(stream)){content reader.ReadToEnd(); }}}Init(new Note(){Title sample,Contentcontent});}private void Init(Note note){if (note ! null){Title note.Title;Content note.Content;}OnInited?.Invoke(this.Content);}private string _title;public string Title{get { return _title; }set{_title value;OnPropertyChanged();}}private string _content;public string Content{get { return _content; }set{_content value;OnPropertyChanged();}}private async void SubmitAction(object obj){var savedContent await OnSubmitting?.Invoke();if (string.IsNullOrEmpty(savedContent)){return;}this.ContentsavedContent;var note new Note();note.Title this.Title;note.Content this.Content;}public Command Submit { get; set; }} 注意这里的Init方法用于初始化内容。这里我们读取Editorjs.Assets.sample1.json资源文件作为初始内容。 创建Blazor组件 创建Blazor页面EditorjsPage.razor 在EditorjsPage.razor页面中我们放置一个div用于放置编辑器 razor页面的 Code 代码段中放置EditNotePageViewModel属性以及一个DotNetObjectReference对象用于在JS中调用C#方法。 code {[Parameter]public IEditorViewModel EditNotePageViewModel { get; set; }private DotNetObjectReferenceEditorjsPage objRef;protected override void OnInitialized(){objRef DotNetObjectReference.Create(this);} 初始化 在script代码段中创建LoadContent函数用于加载EditorJs的初始内容。 div classce-maindiv ideditorjs/div /div LoadContent中调用函数window.editor new window.EditorJS(config)创建一个EditorJS对象其中config对象包括holdertoolsdata等属性关于EditorJs配置的更多说明请参考官方文档 script typetext/javascriptwindow.editor null;window.viewService {LoadContent: function (content) {var obj JSON.parse(content);var createEdtor () {window.editor new window.EditorJS({ holder: editorjs,/*** Tools list*/tools: {paragraph: {config: {placeholder: Enter something}},header: {class: Header,inlineToolbar: [link],config: {placeholder: Header},shortcut: CMDSHIFTH},/*** Or pass class directly without any configuration*/image: {class: ImageTool},list: {class: NestedList,inlineToolbar: true,shortcut: CMDSHIFTL},checklist: {class: Checklist,inlineToolbar: true,},quote: {class: Quote,inlineToolbar: true,config: {quotePlaceholder: 输入引用内容,captionPlaceholder: 引用标题,},shortcut: CMDSHIFTO},marker: {class: Marker,shortcut: CMDSHIFTM},code: {class: CodeTool,shortcut: CMDSHIFTC},delimiter: Delimiter,inlineCode: {class: InlineCode,shortcut: CMDSHIFTC},linkTool: LinkTool,embed: Embed,table: {class: Table,inlineToolbar: true,shortcut: CMDALTT},},i18n: {messages: {ui: {blockTunes: {toggler: {Click to tune: 点击转换,or drag to move: 拖动调整},},inlineToolbar: {converter: {Convert to: 转换成}},toolbar: {toolbox: {Add: 添加,Filter: 过滤,Nothing found: 无内容},popover: {Filter: 过滤,Nothing found: 无内容}}},toolNames: {Text: 段落,Heading: 标题,List: 列表,Warning: 警告,Checklist: 清单,Quote: 引用,Code: 代码,Delimiter: 分割线,Raw HTML: HTML片段,Table: 表格,Link: 链接,Marker: 突出显示,Bold: 加粗,Italic: 倾斜,InlineCode: 代码片段,Image: 图片},tools: {link: {Add a link: 添加链接},stub: {The block can not be displayed correctly.: 该模块不能放置在这里},image: {Caption: 图片说明,Select an Image: 选择图片,With border: 添加边框,Stretch image: 拉伸图像,With background: 添加背景,},code: {Enter a code: 输入代码,},linkTool: {Link: 请输入链接地址,Couldnt fetch the link data: 获取链接数据失败,Couldnt get this link data, try the other one: 该链接不能访问请修改,Wrong response format from the server: 错误响应,},header: {Header: 标题,Heading 1: 一级标题,Heading 2: 二级标题,Heading 3: 三级标题,Heading 4: 四级标题,Heading 5: 五级标题,Heading 6: 六级标题,},paragraph: {Enter something: 请输入笔记内容,},list: {Ordered: 有序列表,Unordered: 无序列表,},table: {Heading: 标题,Add column to left: 在左侧插入列,Add column to right: 在右侧插入列,Delete column: 删除列,Add row above: 在上方插入行,Add row below: 在下方插入行,Delete row: 删除行,With headings: 有标题,Without headings: 无标题,},quote: {Align Left: 左对齐,Align Center: 居中对齐,}},blockTunes: {delete: {Delete: 删除,Click to delete: 点击删除},moveUp: {Move up: 向上移},moveDown: {Move down: 向下移},filter: {Filter: 过滤}},}},/*** Initial Editor data*/data: obj});}if (window.editor) {editor.isReady.then(() {editor.destroy();createEdtor();});}else {createEdtor();}},DumpContent: async function () {outputData null;if (window.editor) {if (window.editor.readOnly.isEnabled) {await window.editor.readOnly.toggle();}var outputObj await window.editor.save();outputData JSON.stringify(outputObj);}return outputData;},SwitchTheme: function () {document.body.classList.toggle(dark-mode);},SwitchState: async function () {state null;if (window.editor window.editor.readOnly) {var readOnlyState await window.editor.readOnly.toggle();state readOnlyState;}return state;},Focus: async function (atEnd) {if (window.editor) {await window.editor.focus(atEnd);}},GetState() {if (window.editor window.editor.readOnly) {return window.editor.readOnly.isEnabled;}},Destroy: function () {if (window.editor) {window.editor.destroy();}},}window.initObjRef function (objRef) {window.objRef objRef;}/script 保存 创建转存函数DumpContent DumpContent: async function () {outputData null;if (window.editor) {if (window.editor.readOnly.isEnabled) {await window.editor.readOnly.toggle();}var outputObj await window.editor.save();outputData JSON.stringify(outputObj);}return outputData; }, 销毁 创建销毁函数Destroy Destroy: function () {if (window.editor) {window.editor.destroy();} },编写渲染逻辑 在OnAfterRenderAsync中调用初始化函数并订阅OnSubmitting和OnInited事件以便在提交事件触发时保存以及文本状态变更时重新渲染。 protected override async Task OnAfterRenderAsync(bool firstRender){if (!firstRender)return;if (EditNotePageViewModel ! null){EditNotePageViewModel.PropertyChanged EditNotePageViewModel_PropertyChanged;this.EditNotePageViewModel.OnSubmitting OnSubmitting;this.EditNotePageViewModel.OnInited OnInited;var currentContent EditNotePageViewModel.Content;await JSRuntime.InvokeVoidAsync(viewService.LoadContent, currentContent);}await JSRuntime.InvokeVoidAsync(window.initObjRef, this.objRef);}private async Taskstring OnSubmitting() {var savedContent await JSRuntime.InvokeAsyncstring(viewService.DumpContent);return savedContent; }private async void OnInited(string content) {await JSRuntime.InvokeVoidAsync(viewService.LoadContent, content); }实现只读/编辑功能 在.NET本机中我们使用枚举来表示编辑状态。 并在控件上设置一个按钮来切换编辑状态。 public enum NoteSegmentState {Edit,PreView }EditNotePageViewModel.cs: ... private NoteSegmentState _noteSegmentState;public NoteSegmentState NoteSegmentState{get { return _noteSegmentState; }set{_noteSegmentState value;OnPropertyChanged();}} EditNotePage.xaml: ... StackLayout RadioButtonGroup.GroupNameStateRadioButtonGroup.SelectedValue{Binding NoteSegmentState,ModeTwoWay}OrientationHorizontalRadioButton Value{x:Static service:NoteSegmentState.Edit}Content编辑/RadioButtonRadioButton Value{x:Static service:NoteSegmentState.PreView}Content预览/RadioButton/StackLayoutEditorjs官方提供了readOnly对象通过toggle()方法可以切换编辑模式和只读模式。 在创建Editorjs实例时也可以通过设置readOnly属性为true即可实现只读模式。 切换模式 在razor页面中创建SwitchState函数用来切换编辑模式和只读模式。 SwitchState: async function () {state null;if (window.editor window.editor.readOnly) {var readOnlyState await window.editor.readOnly.toggle();state readOnlyState;}return state; }, 获取只读模式状态 在razor页面中创建GetState函数用来获取编辑模式和只读模式的状态。 GetState() {if (window.editor window.editor.readOnly) {return window.editor.readOnly.isEnabled;} }, 响应切换事件 我们监听EditNotePageViewModel 的NoteSegmentState属性变更事件当状态改变时调用对应的js方法 private async void EditNotePageViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {if (e.PropertyName nameof(EditNotePageViewModel.NoteSegmentState)){if (EditNotePageViewModel.NoteSegmentStateNoteSegmentState.PreView){var state await JSRuntime.InvokeAsyncbool(viewService.GetState);if (!state){await JSRuntime.InvokeAsyncbool(viewService.SwitchState);}}else if (EditNotePageViewModel.NoteSegmentStateNoteSegmentState.Edit){var state await JSRuntime.InvokeAsyncbool(viewService.GetState);if (state){await JSRuntime.InvokeAsyncbool(viewService.SwitchState);}}} } 实现明/暗主题切换 lib/editorjs/css/main.css中定义了.dark-mode类的样式表 .dark-mode { --color-border-light: rgba(255, 255, 255,.08); --color-bg-main: #212121; --color-text-main: #F5F5F5; }.dark-mode .ce-popover {--color-background: #424242;--color-text-primary: #F5F5F5;--color-text-secondary: #707684;--color-border: #424242; }.dark-mode .ce-toolbar__settings-btn {background: #2A2A2A;border: 1px solid #424242; }.dark-mode .ce-toolbar__plus {background: #2A2A2A;border: 1px solid #424242; }.dark-mode .ce-popover-item__icon {background: #2A2A2A; }.dark-mode .ce-code__textarea {color: #212121;background: #2A2A2A; }.dark-mode .tc-popover {--color-border: #424242;--color-background: #424242; } .dark-mode .tc-wrap {--color-background: #424242; } 在razor页面中添加SwitchTheme函数用于用于切换dark-mode的类名从而实现暗黑模式和正常模式之间的切换。 SwitchTheme: function () {document.body.classList.toggle(dark-mode); },在OnInitializedAsync中订阅Application.Current.RequestedThemeChanged事件用于监听主题切换事件并调用SwitchTheme函数。 protected override async Task OnInitializedAsync() {objRef DotNetObjectReference.Create(this);Application.Current.RequestedThemeChanged OnRequestedThemeChanged;} private async void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs args) {await JSRuntime.InvokeVoidAsync(viewService.SwitchTheme); }在渲染页面时也判断是否需要切换主题 protected override async Task OnAfterRenderAsync(bool firstRender) {if (!firstRender)return;···if (Application.Current.UserAppThemeAppTheme.Dark){await JSRuntime.InvokeVoidAsync(viewService.SwitchTheme);}} 项目地址 Github:maui-samples
http://www.w-s-a.com/news/189957/

相关文章:

  • 网站导航栏设计要求辽宁省住房和城乡建设厅
  • 海外网站平台腾讯营销平台
  • 东道网站建设良品铺子网络营销案例
  • 免费企业查询软件优化模型
  • 兰亭集势的网站平台建设凡科网站免费版怎么做
  • 在网站做推广要钱吗网站根目录是哪个文件夹
  • 网站建设如何弄链接海外vps一键配置WordPress
  • 1个ip可以做几个网站吗动画制作可以自学吗
  • 顺德建设局网站如何搭建网站
  • 精品网站建设费用 干净磐石网络网页制作简单作业
  • 网站建设需要用软件群晖怎样做网站
  • 网站建设公司有哪博客网站建设方案书
  • 服装商城的网站建设宿迁论坛
  • 网站建设服务市场趋势淮南市网站开发的方式
  • 交互设计包含网站设计wordpress和discuz共存
  • 淮阳城乡建设局网站在线网页翻译软件
  • 什么是电商视觉设计郑州seo服务
  • google网站设计原则青海网站建设与管理
  • 简述网站的创建流程广西网站建设定制
  • 唐河网站制作汉中建设工程招标新闻中心
  • 网站过期就可以抢注PHP框架和wordpress
  • 天津做网站得公司克隆网站到wordpress修改
  • 郫县网站建设网站建设报价单及项目收费明细表
  • 商标做网站logo建网站作业
  • 网站顶部展出的大幅广告中建八局第二建设有限公司
  • 公众微信绑定网站帐号优秀中文网页设计
  • 如何做漫画赚钱的网站企业网站管理系统c
  • 安康公司网站制作搜狗网站
  • 太仓住房与城乡建设局网站注册推广赚钱一个80元
  • wordpress 网站生成app企业网站改版的好处