feat: vue3中解析渲染md教程

master
LCJ-MinYa 10 months ago
parent d145ddc07e
commit 1fdbd0ee0d

@ -32,6 +32,7 @@
"dayjs": "^1.11.12", "dayjs": "^1.11.12",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"element-plus": "^2.8.0", "element-plus": "^2.8.0",
"github-markdown-css": "^5.8.1",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"marked": "^15.0.7", "marked": "^15.0.7",

@ -41,6 +41,9 @@ importers:
element-plus: element-plus:
specifier: ^2.8.0 specifier: ^2.8.0
version: 2.8.0(vue@3.4.38(typescript@5.5.4)) version: 2.8.0(vue@3.4.38(typescript@5.5.4))
github-markdown-css:
specifier: ^5.8.1
version: 5.8.1
js-cookie: js-cookie:
specifier: ^3.0.5 specifier: ^3.0.5
version: 3.0.5 version: 3.0.5
@ -1884,6 +1887,10 @@ packages:
resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==}
hasBin: true hasBin: true
github-markdown-css@5.8.1:
resolution: {integrity: sha512-8G+PFvqigBQSWLQjyzgpa2ThD9bo7+kDsriUIidGcRhXgmcaAWUIpCZf8DavJgc+xifjbCG+GvMyWr0XMXmc7g==}
engines: {node: '>=10'}
glob-parent@5.1.2: glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -5414,6 +5421,8 @@ snapshots:
tar: 6.2.1 tar: 6.2.1
optional: true optional: true
github-markdown-css@5.8.1: {}
glob-parent@5.1.2: glob-parent@5.1.2:
dependencies: dependencies:
is-glob: 4.0.3 is-glob: 4.0.3

@ -0,0 +1,107 @@
# [H5 页面中实现跳转到其他 APP](https://www.cnblogs.com/yuzhihui/p/18707478)
在 H5 页面中跳转到其他 APP可以使用以下几种方式
### 1\. **URL Scheme自定义协议**
许多 APP 都支持 URL Scheme 方式的跳转,例如:
```html
| | |
| --- | --- |
| | <a href="weixin://">打开微信</a> |
| | <a href="alipay://">打开支付宝</a> |
| | <a href="yourapp://path">打开自定义 APP</a> |
```
**注意:**
* 需要目标 APP 支持 URL Scheme未安装 APP 时会无响应或报错。
* 在 iOS 9+ 之后,需在 `info.plist` 中配置 `LSApplicationQueriesSchemes`
### 2\. **Universal LinksiOS& Deep LinkAndroid**
Universal LinksiOS和 Deep LinkAndroid可以更安全地跳转到 APP且未安装时可跳转至 Web 页面。
* 需要服务端配置特定文件(如 `apple-app-site-association`)。
* 适用于 iOS 9+,不会弹出确认框,用户体验更好。
**示例:**
```html
| | |
| --- | --- |
| | <a href="https://yourdomain.com/path">打开 APP</a> |
```
### 3\. **Intent SchemeAndroid 专属)**
在 Android 设备上可以使用 `intent://` 方案:
```html
| | |
| --- | --- |
| | <a href="intent://path#Intent;scheme=yourapp;package=com.example.app;end;" |
| | >打开 APP</a |
| | > |
```
* 若 APP 已安装,则直接打开。
* 若 APP 未安装,则可跳转到 Google Play。
### 4\. **iframe 方式(部分浏览器支持)**
```html
| | |
| --- | --- |
| | <iframe src="yourapp://path" style="display: none;"></iframe> |
```
* 可用于尝试静默拉起 APP但可能被浏览器拦截。
### 5\. **混合方式(兼容性方案)**
综合以上方法,推荐使用 JS 处理:
```html
| | |
| --- | --- |
| | <script> |
| | function openApp() { |
| | var schemeUrl = "yourapp://path"; |
| | var storeUrl = "https://yourapp.com/download"; // APP 下载地址 |
| | |
| | var ua = navigator.userAgent.toLowerCase(); |
| | var isAndroid = ua.indexOf("android") > -1; |
| | var isIOS = ua.indexOf("iphone") > -1 \| ua.indexOf("ipad") > -1; |
| | |
| | if (isIOS) { |
| | window.location.href = schemeUrl; |
| | setTimeout(() => { |
| | window.location.href = storeUrl; |
| | }, 2000); |
| | } else if (isAndroid) { |
| | window.location.href = schemeUrl; |
| | setTimeout(() => { |
| | window.location.href = storeUrl; |
| | }, 2000); |
| | } else { |
| | window.location.href = storeUrl; |
| | } |
| | } |
| | </script> |
| | |
| | <button onclick="openApp()">打开 APP</button> |
```
### **总结**
| 方式 | 适用平台 | 适用场景 | 适配难度 |
| --- | --- | --- | --- |
| URL Scheme | iOS/Android | 适用于已知 APP | 低 |
| Universal Links / Deep Link | iOS/Android | 更安全,适用于已安装 APP | 高 |
| Intent Scheme | Android | 适用于 Android | 中 |
| iframe | 部分浏览器 | 适用于尝试拉起 APP | 低 |
| 综合方案 | iOS/Android | 适用于多种情况 | 中 |
如果 APP 需要兼容性更好的跳转方式,建议结合 Universal LinksiOS和 Deep LinkAndroid

@ -0,0 +1,78 @@
# Vue3中渲染markdown教程
### 1. 安装md插件
```shell
pnpm add marked
```
### 2. 安装美化样式
- **安装`github-markdown-css`**
```shell
pnpm add github-markdown-css
```
- **在main.js中全局引入样式如果单个页面使用可以直接页面中引入即可**
```javascript
import 'github-markdown-css/github-markdown.css'
```
- **reset.scss初始化样式中添加如下代码**
```scss
// markdown 解析格式美化
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 100%;
margin: 0 auto;
padding: 20px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
```
### 3. 页面使用
```vue3
<template>
<div
class="markdown-body"
v-html="htmlStr"
/>
</template>
<script setup>
import { ref } from 'vue';
import { marked } from 'marked';
import { getMarkdownContent } from '@/utils/tools';
const htmlStr = ref('');
getMarkdownContent('./md/vue3中渲染markdown.md').then((res) => {
htmlStr.value = marked(res);
});
</script>
```
getMarkdownContent方法实现
```javascript
/** 获取远程资源markdown内的内容 */
export const getMarkdownContent = (filePath) => {
return new Promise((resolve, reject) => {
fetch(filePath, {
method: 'GET',
})
.then((result) => {
result
.text()
.then((res) => {
resolve(res);
})
.catch((err) => reject(err));
})
.catch((err) => reject(err));
});
};
```

@ -22,6 +22,8 @@ import 'element-plus/dist/index.css';
// 导入字体图标 // 导入字体图标
import './assets/iconfont/iconfont.js'; import './assets/iconfont/iconfont.js';
import './assets/iconfont/iconfont.css'; import './assets/iconfont/iconfont.css';
// github-markdown-css 全局md样式美化
import 'github-markdown-css/github-markdown.css';
const app = createApp(App); const app = createApp(App);

@ -37,5 +37,14 @@ export default {
keepAlive: true, keepAlive: true,
}, },
}, },
{
path: '/template/markdown',
name: 'TemplateMarkdown',
component: () => import('@/views/template/markdown/index.vue'),
meta: {
title: 'Markdown模版',
keepAlive: true,
},
},
], ],
} satisfies RouteConfigsTable; } satisfies RouteConfigsTable;

@ -255,23 +255,16 @@ div:focus {
} }
// markdown // markdown
.md-main { .markdown-body {
p, box-sizing: border-box;
ul, min-width: 200px;
ol { max-width: 100%;
margin: 16px 0; margin: 0 auto;
} padding: 20px;
h3 { }
margin: 18px 0;
} @media (max-width: 767px) {
ul, .markdown-body {
ol { padding: 15px;
padding-left: 40px;
list-style: disc;
}
hr {
margin: 40px 0;
height: 10px;
background: #f5f5f5;
} }
} }

@ -0,0 +1,18 @@
<template>
<div
class="markdown-body"
v-html="htmlStr"
></div>
</template>
<script setup>
import { ref } from 'vue';
import { marked } from 'marked';
import { getMarkdownContent } from '@/utils/tools';
const htmlStr = ref('');
getMarkdownContent('./md/h5唤起app.md').then((res) => {
htmlStr.value = marked(res);
});
</script>

@ -1,11 +1,11 @@
<template> <template>
<el-card> <div>
<img src="./img/1.png" /> <img src="./img/1.png" />
<div <div
class="md-main" class="markdown-body"
v-html="htmlStr" v-html="htmlStr"
></div> ></div>
</el-card> </div>
</template> </template>
<script setup> <script setup>

@ -1,10 +1,8 @@
<template> <template>
<el-card> <div
<div class="markdown-body"
class="md-main" v-html="htmlStr"
v-html="htmlStr" ></div>
></div>
</el-card>
</template> </template>
<script setup> <script setup>

@ -0,0 +1,18 @@
<template>
<div
class="markdown-body"
v-html="htmlStr"
/>
</template>
<script setup>
import { ref } from 'vue';
import { marked } from 'marked';
import { getMarkdownContent } from '@/utils/tools';
const htmlStr = ref('');
getMarkdownContent('./md/vue3中渲染markdown.md').then((res) => {
htmlStr.value = marked(res);
});
</script>
Loading…
Cancel
Save