Blazor組件自做一 : 使用JS隔離封裝viewerjs庫

来源:https://www.cnblogs.com/densen2014/archive/2022/03/20/16027851.html
-Advertisement-
Play Games

Viewer.js庫是一個實用的js庫,用於圖片瀏覽,放大縮小翻轉幻燈片播放等實用操作 本文相關參考鏈接 JavaScript 模塊中的 JavaScript 隔離 Viewer.js工程 Blazor JS 隔離優勢 導入的 JS 不再污染全局命名空間。 庫和組件的使用者不需要導入相關的 JS。即 ...


Viewer.js库是一个实用的js库,用于图片浏览,放大缩小翻转幻灯片播放等实用操作

本文相关参考链接

  1. JavaScript 模块中的 JavaScript 隔离
  2. Viewer.js工程

Blazor JS 隔离优势

导入的 JS 不再污染全局命名空间。
库和组件的使用者不需要导入相关的 JS。即不需要再在ssr的 Pages/_Host.cshtml 或 Pages/_Layout.cshtml ,wasm的 wwwroot/index.html 里写
第一遍载入静态资产请求包含值为 no-cache 或 max-age(值为零 (0))的 标头。真正页面组件使用才载入真实大小文件。

正式开始

1. 打开VS2020, 新建工程面板, 项目模板搜索 blazor , 选择Blazor Server应用. (wasm也可以,但是不好调试,先从简单的SSR入手)

image

2. 工程名称改为Blazor100,下一步,默认设置, 保存.

image
image

3. 右键点击wwwroot文件夹,添加lib文件夹,添加viewerjs子文件夹,里面添加viewerjs.js文件 . 最终版本参考如下

image
image

4. 编写js文件. 首先在这个步骤我们使用在线版本的js库,这样操作和理解都比较简单. 然后是一个title函数,用于使用图片alt和索引信息生成viewer.js组件的标题, viewer.js组件初始化. 接下来是注销组件过程.
viewer.js代码
import 'https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.js';
var viewer = null;
export function initOptions(options) {
    options.title = function (image) {
        return image.alt + ' (' + (this.index + 1) + '/' + this.length + ')';
    };
    //options.hidden= function () {
    //    viewer.destroy();
    //};
    if (undefined !== options.toolbarlite && options.toolbarlite == true) {
        options.toolbar = {
            zoomIn: true,
            zoomOut: true,
            //rotateLeft: true,
            rotateRight: true,
            //prev: true,
            //next: true,
        };
    }
    if (undefined !== viewer && null !== viewer && options.id == viewer.element.id) {
        viewer.destroy();
        console.log(viewer.element.id, 'destroy');
    }
    viewer = new Viewer(document.getElementById(options.id), options);
    console.log(viewer.element.id);
}
export function destroy(options) {
    if (undefined !== viewer && null !== viewer && options.id == viewer.element.id) {
        viewer.destroy();
        console.log(viewer.element.id, 'destroy');
    }
}
5. 新建Components文件夹 , 新建Viewerjs.razor组件

image

组件的命名空间统一使用Blazor100.Components,在razor文件和razor.cs都使用统一命名空间,这样不会受到文件夹嵌套各种影响.

Viewerjs.razor代码
@implements IAsyncDisposable
@inject IJSRuntime JS
@namespace Blazor100.Components

@if (UseBuiltinImageDiv)
{
    <div class="docs-galley mb-3" style="height: @Height;width:@Width; ">
        <ul id="@Options.id" class="docs-pictures clearfix">
            @{
                var i = 0;
                foreach (var item in Images)
                {
                    var alt = (Alts != null && Alts.Any() && Alts.Count > i) ? Alts[i] : (item.Split('/').Last());
                    <li><img src="@item" alt="@alt"></li>
                    i++;
                }
            }
        </ul>
    </div>
}

<link href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.css" rel="stylesheet" />

@code{
    /// <summary>
    /// 使用内置图片DIV
    /// </summary>
    [Parameter] public bool UseBuiltinImageDiv { get; set; } = true;

    /// <summary>
    /// 图片列表
    /// </summary>
    [Parameter] public List<string> Images { get; set; } = new List<string>();

    /// <summary>
    /// 单图片
    /// </summary>
    [Parameter] public string? Src { get; set; }

    /// <summary>
    /// 图片名称列表
    /// </summary>
    [Parameter] public List<string>? Alts { get; set; }

    /// <summary>
    /// 组件初始化参数
    /// </summary>
    [Parameter] public ViewerOptions Options { get; set; } = new ViewerOptions();

    /// <summary>
    /// 简化版工具条
    /// </summary>
    [Parameter] public bool? toolbarlite { get; set; }

    /// <summary>
    /// 高
    /// </summary>
    [Parameter] public string? Height { get; set; } = "400px";

    /// <summary>
    /// 宽
    /// </summary>
    [Parameter] public string? Width { get; set; } = "400px";

    /// <summary>
    /// 组件ID
    /// </summary>
    [Parameter] public string? ID { get; set; }

    private IJSObjectReference? module;

    protected override void OnInitialized()
    {
        Options ??= new ViewerOptions();
        if (toolbarlite != null) Options.toolbarlite = toolbarlite.Value;
        if (!string.IsNullOrEmpty(ID)) Options.id = ID; else Options.id = Guid.NewGuid().ToString();
        Images ??= new List<string>();
        if (Src != null)
            Images.Add(Src);
        else if (!Images.Any())
        {
            for (int i = 1; i <= 9; i++)
            {
                Images.Add("./favicon.ico");
            }
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import", "/lib/viewerjs/viewerjs.js");
            await module.InvokeVoidAsync("initOptions", Options);
        }
    }

    public async Task OnOptionsChanged(ViewerOptions options) => await module!.InvokeVoidAsync("initOptions", options);

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.InvokeVoidAsync("destroy", Options);
            await module.DisposeAsync();
        }
    }
}

6. 添加 Viewerjs.razor.css 文件.
Viewerjs.razor.css代码
.docs-galley {
    padding: 10px;
    width: 400px;
}

.docs-pictures {
    list-style: none;
    margin: 0;
    padding: 0;
}

    .docs-pictures > li {
        border: 1px solid transparent;
        float: left;
        height: calc(100% / 3);
        margin: 0 -1px -1px 0;
        overflow: hidden;
        width: calc(100% / 3);
    }

        .docs-pictures > li > img {
            cursor: -webkit-zoom-in;
            cursor: zoom-in;
            width: 100%;
        }

img {
    vertical-align: middle;
    border-style: none;
}
7. 图片浏览器选项类

类命名空间统一使用Blazor100.Components,在.cs都使用统一命名空间.

Viewerjs.razor代码
using System.ComponentModel;


namespace Blazor100.Components;

/// <summary>
/// 图片浏览器选项类
/// </summary>
public class ViewerOptions
{
    /// <summary>
    /// 图片浏览器选项
    /// </summary>
    /// <param name="id"></param>
    /// <param name="fullscreen"></param>
    public ViewerOptions(string id = "images", bool fullscreen = true)
    {
        this.id = id;
        this.fullscreen = fullscreen;
    }
    public string id { get; set; } = "images";

    /// <summary>
    /// 简化版工具条
    /// </summary>
    public bool toolbarlite { get; set; }
    public string container { get; set; } = "body";

    /// <summary>
    /// 背景遮罩
    /// </summary>
    [DisplayName("背景遮罩")]
    public bool backdrop { get; set; } = true;

    /// <summary>
    /// 右上角的关闭按钮
    /// </summary>
    [DisplayName("关闭按钮")]
    public bool button { get; set; } = true;

    public bool focus { get; set; } = true;

    /// <summary>
    /// 全屏
    /// </summary>
    [DisplayName("全屏")]
    public bool fullscreen { get; set; } = true;

    /// <summary>
    /// 内联/模态模式
    /// </summary>
    [DisplayName("内联/模态模式")]
    public bool inline { get; set; } = false;

    /// <summary>
    /// 
    /// </summary>
    public int interval { get; set; } = 5000;

    /// <summary>
    /// 键盘导航快捷键
    /// </summary>
    [DisplayName("键盘导航快捷键")]
    public bool keyboard { get; set; } = true;

    /// <summary>
    /// 
    /// </summary>
    public bool loading { get; set; } = true;

    /// <summary>
    /// 循环播放
    /// </summary>
    [DisplayName("循环播放")]
    public bool loop { get; set; } = true;

    /// <summary>
    /// 
    /// </summary>
    public int maxZoomRatio { get; set; } = 100;

    /// <summary>
    /// 
    /// </summary>
    public int minHeight { get; set; } = 100;

    /// <summary>
    /// 
    /// </summary>
    public int minWidth { get; set; } = 200;

    /// <summary>
    /// 
    /// </summary>
    public double minZoomRatio { get; set; } = 0.01;

    /// <summary>
    /// 可移动
    /// </summary>
    [DisplayName("可移动")]
    public bool movable { get; set; } = true;

    /// <summary>
    /// 导航
    /// </summary>
    [DisplayName("导航")]
    public bool navbar { get; set; } = true;

    /// <summary>
    /// 可旋转
    /// </summary>
    [DisplayName("可旋转")]
    public bool rotatable { get; set; } = true;

    /// <summary>
    /// 可缩放
    /// </summary>
    [DisplayName("可缩放")]
    public bool scalable { get; set; } = true;

    /// <summary>
    /// 滑动触摸
    /// </summary>
    [DisplayName("滑动触摸")]
    public bool slideOnTouch { get; set; } = true;

    /// <summary>
    /// 标题
    /// </summary>
    [DisplayName("标题")]
    public bool title { get; set; } = true;

    /// <summary>
    /// 双击切换
    /// </summary>
    [DisplayName("双击切换")]
    public bool toggleOnDblclick { get; set; } = true;

    /// <summary>
    /// 工具栏
    /// </summary>
    [DisplayName("工具栏")]
    public bool toolbar { get; set; } = true;

    /// <summary>
    /// 工具提示
    /// </summary>
    [DisplayName("工具提示")]
    public bool tooltip { get; set; } = true;

    /// <summary>
    /// 过渡效果
    /// </summary>
    [DisplayName("过渡效果")]
    public bool transition { get; set; } = true;

    /// <summary>
    /// 触摸缩放
    /// </summary>
    [DisplayName("触摸缩放")]
    public bool zoomOnTouch { get; set; } = true;

    /// <summary>
    /// 滚轮缩放
    /// </summary>
    [DisplayName("触摸缩放")]
    public bool zoomOnWheel { get; set; } = true;

    /// <summary>
    /// 缩放率
    /// </summary>
    [DisplayName("缩放率")]
    public double zoomRatio { get; set; } = 0.1;

    /// <summary>
    /// 可缩放
    /// </summary>
    [DisplayName("可缩放")]
    public bool zoomable { get; set; } = true;
}
8. Pages文件添加ViewerPage.razor文件,用于演示组件调用
Viewerjs.razor代码
@page "/viewer"

<Viewerjs Images="imagesList" />

@code{
    List<string>? imagesList;

    protected override void OnInitialized()
    {
        imagesList = new List<string>();
        if (!imagesList.Any())
        {
            for (int i = 1; i <= 9; i++)
            {
                imagesList.Add($"https://fengyuanchen.github.io/viewerjs/images/thumbnails/tibet-{i}.jpg");
            }
        }
    }

}
9. _Imports.razor加入一行引用组件的命名空间
@using Blazor100.Components

image

10. 首页引用组件演示页 <ViewerPage />

首页引用演示页

11. F5运行程序,将会自动打开浏览器调试

v1

v

至此,使用JS隔离封装的viewerjs库大功告成!

如果需要断网环境使用此库,需要把库文件和css文件下载放到wwwroot/lib/viewerjs文件夹里面,上面两个文件需要修改一下:
步骤4的viewer.js代码


import 'https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.js';

import '/lib/viewerjs/viewer.min.js';


步骤5的Viewerjs.razor代码


href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.css"

href="/lib/viewerjs/viewer.min.css"


Blazor组件自做系列

Blazor组件自做一 : 使用JS隔离封装viewerjs库
Blazor组件自做二 : 使用JS隔离制作手写签名组件
Blazor组件自做三 : 使用JS隔离封装ZXing扫码
Blazor组件自做四: 使用JS隔离封装signature_pad签名组件
Blazor组件自做五: 使用JS隔离封装Google地图<03-24>
Blazor组件自做六: 使用JS隔离封装Baidu地图<03-25>
Blazor组件自做七: 使用JS隔离制作定位/持续定位组件<03-26>
Blazor组件自做八: 使用JS隔离封装屏幕键盘kioskboard.js组件<03-27>

项目源码 Github | Gitee

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.什麼是Blazor? 有什麼優勢? ASP.NET Core Blazor 簡介 Blazor 是一個使用 Blazor 生成互動式客戶端 Web UI 的框架: 使用 C# 代替 JavaScript 來創建信息豐富的互動式 UI。 共用使用 .NET 編寫的伺服器端和客戶端應用邏輯。 將 U ...
  • 配置源的同步 IOptionsMonitor 使用 //以下demo演示使用IOptionsMonitor重新載入配置並當重新載入配置是執行回調函數 var configuration = new ConfigurationBuilder().AddJsonFile(path: "profile.j ...
  • 十天前,我發佈了對.NET Core程式進行瘦身的開源軟體Zack.DotNetTrimmer,與.NET Core內置的剪裁器相比,Zack.DotNetTrimmer不僅對程式的剪裁效果更好,而且還支持WPF、WinForm程式。 很多朋友對於這個開源項目的原理很感興趣,因此我將通過這篇文章為大 ...
  • 1. 前言 通過之前的學習,我們已經瞭解了各參數以及配置的意義,接下來的文章我們分別從bombardier以及wrk入手,進一步瞭解彼此之間的聯繫 2. 認識 bombardier bombardier 是一個 HTTP(S) 基準測試工具。它是用 Go 編程語言編寫的,並使用優秀的fasthttp ...
  • 一 發佈者和訂閱者 很多時候都有這種需求,當一個特定的程式事件發生時,程式的其他部分可以得到該事件已經發生的通知。 發佈者/訂閱者模式可以滿足這種需求。 發佈者:發佈某個事件的類或結構,其他類可以在該事件發生時得到通知。 訂閱者:註冊併在事件發生時得到通知的類或結構。 事件處理程式:由訂閱者註冊到事 ...
  • Net6 Configuration & Options 源碼分析 Part2 Options 第二部分主要記錄Options 模型 OptionsConfigurationServiceCollectionExtensions類提供了對Options 模型與配置系統的Configure方法的擴展 ...
  • 1. 前言 WPF 的 TextBlock 提供了大部分常用的文字修飾方法,在日常使用中基本夠用。如果需要更豐富的表現方式,WPF 也提供了其它用起來複雜一些的工具去實現這些需求。例如這篇文章介紹的文字描邊,就有幾種方法可以在 WPF 中呈現。這篇文章將簡單介紹這實現文字描邊的方法。 2. 將文字轉 ...
  • 今天我們一起來探索一下ASP.NET Core框架中的Authorization。我們知道請求進入管道處理流程先會使用Authentication進行用戶認證,然後使用Authorization進行用戶授權。如果沒有看過認證過程的大家可以先轉到Authentication這一篇。 AddAuthor ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...