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


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM