location.href相比较<a>标签的下载

简化下载操作
本文介绍了一种简化页面下载功能的方法,通过使用location.href替代传统的a标签,实现根据不同系统自动下载相应文件的功能,使得代码更加简洁。

如果页面上要实现一个点击下载的功能,传统做法是使用一个 a 标签,然后将该标签的 href 属性地址指向下载文件在服务端的地址(相对地址或者绝对地址)


能这样实现是因为,在浏览器地址栏输入一个文件地址,如果该文件能在浏览器上打开,那么就直接打开,比如 html 文件,jpg文件等;但是如果该文件不能在浏览器上打开,就会变为下载。

但是有时候这样做会显得有点复杂。比如说我在一个移动端页面定义了一个 app 的下载按钮,显然下载地址会根据机器系统(Android 或者 ios)需要判断,这样就要在 javascript 重置 a 标签的 href 属性。我们十分想要一个 download 函数,能够监听任何 dom 元素,然后完成下载操作,而不仅仅是 a 标签,答案是有的,location.href 可以做到。

的确,既然 a 标签打开一个文件能实现下载功能,那么用 location.href 就也能做到了。

if (isIphone) {
location.href = ‘…’;// 仅仅这行代码就可以实现页面无切换,无跳闪的下载。
} else {
location.href = ‘…’;
}


**这样,html 端就清净多了。**
<template> <view class="record-screen-page"> <!-- 导航栏区域 --> <view class="navbar"> <view class="nav-back" @click="onBack">←</view> <view class="nav-title">录屏取证</view> </view> <!-- 主体内容区域 --> <view class="content"> <!-- 自定义名称输入框 --> <input class="native-input" type="text" placeholder="输入自定义名称 (选填,不会显示在证书上)" v-model="customName" /> <!-- 开始录屏按钮 --> <button class="record-btn" @click="startRecord"> <text class="record-text">开始录屏</text> </button> <!-- 底部操作区 --> <view class="bottom-bar"> <view class="bottom-bar-top"> <text class="guide-text">操作指引</text> <view class="switch-group" v-if="isAndroid"> <text class="switch-label">麦克风:</text> <switch :checked="micEnabled" @change="handleMicChange" /> </view> </view> <!-- 调整这部分的样式类名,方便单独控制 --> <view class="switch-group position-switch-group"> <text class="switch-label">在证书上显示位置信息:</text> <switch :checked="showLocation" @change="showLocation = $event.detail.value" /> </view> </view> </view> </view> </template> <script> const SCREEN_RECORDER_PLUGIN = 'ScreenRecorderModule'; export default { data() { return { customName: '', showLocation: false, micEnabled: false, isAndroid: false, isRecording: false, recordingStatus: '', recorder: null } }, onLoad() { // 检测平台 const platform = uni.getSystemInfoSync().platform; this.isAndroid = platform === 'android'; // 加载原生插件 // #ifdef APP-PLUS this.recorder = uni.requireNativePlugin(SCREEN_RECORDER_PLUGIN); // #endif }, methods: { onBack() { uni.navigateBack(); }, async handleMicChange(event) { const checked = event.detail.value; if (checked) { const authResult = await this.requestMicrophonePermission(); this.micEnabled = authResult; } else { this.micEnabled = false; } }, requestMicrophonePermission() { return new Promise((resolve) => { uni.authorize({ scope: 'scope.record', success: () => resolve(true), fail: () => { uni.showModal({ title: '权限申请', content: '需要麦克风权限', success: (res) => { if (res.confirm) { uni.openSetting({ success: (setting) => { resolve(setting.authSetting['scope.record'] === true); } }); } else { resolve(false); } } }); } }); }); }, async toggleRecording() { if (this.isRecording) { await this.stopRecording(); } else { await this.startRecording(); } }, async startRecording() { // 权限检查 if (this.micEnabled && this.isAndroid) { const authorized = await this.requestMicrophonePermission(); if (!authorized) { uni.showToast({ title: '请开启麦克风权限', icon: 'none' }); return; } } // 调用原生录屏 // #ifdef APP-PLUS try { this.recorder.startRecording({ micEnabled: this.micEnabled, fileName: this.customName || '取证录屏' }, (result) => { if (result.code === 0) { this.isRecording = true; this.recordingStatus = '录制中...'; } else { uni.showToast({ title: `开始失败: ${result.msg}`, icon: 'none' }); } }); } catch (e) { uni.showToast({ title: '录屏插件加载失败', icon: 'none' }); } // #endif // H5端模拟 // #ifdef H5 this.isRecording = true; this.recordingStatus = 'H5模拟录制中...'; uni.showToast({ title: '请使用App端进行实际录屏', icon: 'none' }); // #endif }, async stopRecording() { // #ifdef APP-PLUS try { this.recorder.stopRecording((result) => { if (result.code === 0) { this.handleRecordingResult(result); } else { uni.showToast({ title: `结束失败: ${result.msg}`, icon: 'none' }); } }); } catch (e) { console.error('录屏停止异常', e); } // #endif // H5端模拟 // #ifdef H5 this.isRecording = false; this.recordingStatus = '录制完成 (模拟)'; uni.showModal({ title: '录屏完成', content: '视频已保存到模拟相册', showCancel: false }); // #endif }, handleRecordingResult(result) { this.isRecording = false; this.recordingStatus = '录制完成'; uni.showModal({ title: '录屏取证完成', content: `视频已保存到: ${result.filePath}`, confirmText: '查看', success: (res) => { if (res.confirm) { // 保存取证信息到本地 this.saveEvidenceInfo(result); // 打开视频 uni.openDocument({ filePath: result.filePath, showMenu: true }); } } }); }, saveEvidenceInfo(recordData) { const evidence = { name: this.customName || '录屏取证', timestamp: new Date().getTime(), location: this.showLocation ? '已记录位置' : '未记录', filePath: recordData.filePath, duration: recordData.duration, size: recordData.fileSize }; // 保存到本地存储 let evidences = uni.getStorageSync('screenEvidences') || []; evidences.unshift(evidence); uni.setStorageSync('screenEvidences', evidences); } } } </script> <style scoped> /* 页面基础布局 */ .record-screen-page { background-color: #fff; min-height: 100vh; } /* 导航栏样式 */ .navbar { background-color: #2E8BFF; height: 200rpx; position: relative; } .nav-back { position: absolute; left: 32rpx; top: 50%; transform: translateY(-50%); font-size: 36rpx; color: #ffffff; } .nav-title { text-align: center; font-size: 36rpx; color: #ffffff; font-weight: bold; line-height: 200rpx; } /* 内容区域间距 */ .content { padding: 40rpx 32rpx; background-color: #dde8fd; } /* 输入框样式 */ .native-input { height: 80rpx; line-height: 80rpx; border: 1px solid #DCDCDC; border-radius: 16rpx; padding: 0 24rpx; font-size: 28rpx; background-color: #FFFFFF; margin-bottom: 40rpx; } /* 录屏按钮样式 */ .record-btn { display: flex; align-items: center; justify-content: center; background-color: #2E8BFF; color: #FFF; font-size: 32rpx; font-weight: bold; height: 96rpx; border-radius: 48rpx; margin-bottom: 60rpx; } /* 底部操作区布局 */ .bottom-bar { display: flex; flex-direction: column; /* 让内部元素纵向排列 */ gap: 10rpx; /* 行与行之间的间距,可根据需求调整 */ } /* 底部操作区第一行样式,实现两端对齐 */ .bottom-bar-top { display: flex; justify-content: space-between; align-items: center; width: 100%; } .guide-text { font-size: 28rpx; color: #999; } .switch-group { display: flex; align-items: center; } /* 新增的样式,用于让“在证书上显示位置信息:”所在行右对齐 */ .position-switch-group { justify-content: flex-end; } .switch-label { font-size: 28rpx; color: #666; margin-right: 12rpx; } .status-text { text-align: center; font-size: 28rpx; color: #2E8BFF; margin: 20rpx 0 40rpx; } /* 录制中按钮样式 */ .record-btn.recording { background-color: #FF4D4F; animation: pulse 1.5s infinite; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } } </style> 修改这个代码 完成APPH5端的录屏 操作
最新发布
08-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值