Blazor组件自做一 : 使用JS隔离封装viewerjs库
Viewer.js库是一个实用的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入手)
2. 工程名称改为Blazor100,下一步,默认设置, 保存.
3. 右键点击wwwroot文件夹,添加lib文件夹,添加viewerjs子文件夹,里面添加viewerjs.js文件 . 最终版本参考如下
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组件
组件的命名空间统一使用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
10. 首页引用组件演示页 <ViewerPage />
11. F5运行程序,将会自动打开浏览器调试
至此,使用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
Blazor组件自做一 : 使用JS隔离封装viewerjs库的更多相关文章
- Blazor组件自做八 : 使用JS隔离封装屏幕键盘kioskboard.js组件
1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加kioskboard子文件夹,添加kioskboards.js文件 2.1 常规操作,懒加载js库, export function ...
- Blazor组件自做三 : 使用JS隔离封装ZXing扫码
Blazor组件自做三 : 使用JS隔离封装ZXing扫码 本文基础步骤参考前两篇文章 Blazor组件自做一 : 使用JS隔离封装viewerjs库 Blazor组件自做二 : 使用JS隔离制作手写 ...
- Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件
运行截图 演示地址 响应式演示 感谢szimek写的棒棒的signature_pad.js项目, 来源: https://github.com/szimek/signature_pad 正式开始 1. ...
- Blazor组件自做五 : 使用JS隔离封装Google地图
Blazor组件自做五: 使用JS隔离封装Google地图 运行截图 演示地址 正式开始 1. 谷歌地图API 谷歌开发文档 开始学习 Maps JavaScript API 的最简单方法是查看一个简 ...
- Blazor组件自做六 : 使用JS隔离封装Baidu地图
1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加baidu子文件夹,添加baidumap.js文件 2.1 跟上一篇类似,用代码方式异步加载API,脚本生成新的 body > ...
- Blazor组件自做二 : 使用JS隔离制作手写签名组件
Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...
- Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (3)
接上篇 Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (2) 7. 使用配置文件指定监听地址 打开 appsettings.json 文件,加入一行 "UseUrls&q ...
- 【Node.js 自己封装的库 http_parse, libuv】
[Node.js 自己封装的库 http_parse, libuv] Node.js 介绍:一个网络框架,更多:http://www.oschina.net/p/nodejs 官网:http://no ...
- Blazor组件自做十一 : File System Access 文件系统访问 组件
Blazor File System Access 文件系统访问 组件 Web 应用程序与用户本地设备上的文件进行交互 File System Access API(以前称为 Native File ...
随机推荐
- 被广泛使用的OAuth2.0的密码模式已经废了,放弃吧
最近一直有同学在问,OAuth2密码模式为啥Spring Security还没有实现,就连新的Spring Authorization Server也没有这个玩意儿. 其实这里可以告诉大家,OAuth ...
- ffmpeg修改视频文件的分辨率
在本文中,我们将展示如何调整任何视频文件的大小. 这种方法是在Linux系统(几乎任何发行版)中调整视频文件大小的最佳方法之一,也是Windows和Mac用户的绝佳替代方案. 更改视频文件的分辨率将是 ...
- 一些JDK自带的性能分析利器
有时候碰到服务器CPU飙升或者程序卡死之类的问题,一般都不太好定位.这类bug一般都隐藏的比较深并且还可能是偶发性的,比较棘手. 对于此类问题,一般我们都有固定的分析流程.借助于JDK自带的一些分析工 ...
- pycharm实用常用快捷键
我们在实用pycharm时候,可以使用一些快捷键来帮助我们写代码. 1 alt + enter 快速导包,在需要导入包时候可以使用这个快捷键: 2 alt + 1 可以快速打开或者关闭左侧projec ...
- CSI 工作原理与JuiceFS CSI Driver 的架构设计详解
容器存储接口(Container Storage Interface)简称 CSI,CSI 建立了行业标准接口的规范,借助 CSI 容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载.Ju ...
- RabbitMQ Go客户端教程6——RPC
本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第六篇--RPC. 这些教程涵盖了使用RabbitMQ创建消息传递应用 ...
- RDMA相关的技术网站
https://www.cnblogs.com/vlhn/p/7909893.html https://www.cnblogs.com/vlhn/ 这个家伙的博客写的还不错,可以参考.
- 亚马逊云储存器S3 BCUKET安全性学习笔记
亚马逊云储存器S3 BCUKET安全性学习笔记 Bugs_Bunny CTF – Walk walk CTF 昨天玩了会这个比赛,碰到这题是知识盲点,来记录一下. 先从题目看起吧. http://ww ...
- Windows&Linux文件传输方式总结
在渗透过程中,通常会需要向目标主机传送一些文件,来达到权限提升.权限维持等目的,本篇文章主要介绍一些windows和Linux下常用的文件传输方式. Windows 利用FTP协议上传 在本地或者VP ...
- linux安装maven环境
linux安装maven环境 一. 下载压缩包: 官网地址: http://maven.apache.org/download.cgi 或者百度网盘链接:https://pan.baidu.com/s ...