背景
阳光沙滩提供的api中返回文章详情,由于网页没有适配移动端需要app开发者自己实现,最简单方式就是康师傅直接适配移动端,我们使用文章id直接访问就行了。移动端原生显示web本来不太适用,下面我们开始最简单网页+webview加载文章详情开发,使用vue,和简单媒体查询。看看效果。
工具
我使用的是JetBrains WebStorm 2019.2.4 x64
创建项目
创建一个vue
项目,创建完成后,我们跑起来先。
这个很简单,跑起来了,安装我们需要的依赖
npm i vue-markdown-loader -D
npm i vue-loader vue-template-compiler -D
继续安装语法高亮
npm install highlight.js -D
npm install github-markdown-css
网络请求
npm install axios
配置loader和网络
在项目根目录下创建一个配置文件vue.config.js,内容如下,直接复制
chainWebpack: (config) => {
config.module
.rule('markdown')
.test(/\.md$/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('vue-markdown-loader')
.loader('vue-markdown-loader/lib/markdown-compiler')
.options({
preset: 'default',
breaks: true,
raw: true,
typographer: true,
})
},
module.exports = {
//打包到手机上面跑,需要做资源路径定位,下面这个代码处理
publicPath : './',
devServer: {
}
}
把康师傅之前提供的网络请求封装文件丢进去。
api文件直接写就行了,内容如下,只有一个接口
import http from "./http";
export const success_code = 10000;
export const BASE_URL = 'https://api.sunofbeach.net';
//获取文章详情,包含标题,内容,用户信息
export const getArticleDetail2 = (articleId) => {
return http.requestGet(BASE_URL + '/ct/article/detail/' + articleId);
}
加载文章详情
进入App.vue
,这里就是我们文章详情的页面,修改代码,身体部分是这样的
<template>
<div id="app">
<div class="container">
<div class="markdown-body sob-article-content" v-html="article_content">
</div>
</div>
</div>
</template>
就这?没错就这。
剩下的就是网络请求
mounted() {
this.httpGetArticle();
highlightCode();
},
methods: {
httpGetArticle() {
//1422385783846830082 1411666843780882434
api.getArticleDetail2(this.articleId).then(resp => {
if (api.success_code === resp.code) {
this.article_content = resp.data.content;
}
});
}
}
我们在路径中获取文章id
created() {
const url = window.location.href;
console.log("获取完整url:" + url);
const para = url.split('?')[1];
console.log("获取第一个参数:" + para);
this.articleId = para.split('=')[1];
console.log("获取数值 " + this.articleId);
},
语法高亮
// 代码高亮
// 其他元素使用 github 的样式
import 'github-markdown-css'
import 'highlight.js/styles/default.css'
import hljs from 'highlight.js'
const highlightCode = () => {
const preEl = document.querySelectorAll('pre')
preEl.forEach((el) => {
hljs.highlightBlock(el)
})
}
挂载和更新调用这个就ok,直接使用你的高级技能CV
mounted,updated -> highlightCode();
样式部分,重点是媒体查询设置
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: left;
color: #2c3e50;
margin-top: 10px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 750px;
min-height: 600px;
width: 100%;
margin: 0 auto;
padding: 20px 20px;
background-color: white;
}
.image-wrap img {
max-width: 100%;
}
.sob-article-content {
max-width: 100%;
}
.sob-article-content pre code {
max-width: 100%;
}
/*img 设置max-width有效*/
.sob-article-content img {
margin-top: 10px;
max-width: 100%;
cursor: zoom-in;
}
/* 大于等于750px作用,同理max-width为小于等于下作用 不同屏幕的特殊处理,下面是例子 */
@media (min-width: 750px) {
.title {
font-size: 24px;
}
}
@media (max-width: 750px) {
.summary {
font-size: 14px;
}
}
</style>
限制最大宽度750px
,viewport
使用,这是我一个前端朋友给我代码,具体也没告诉什么意思,自己百度吧,他把代码给我之后就没说了,让我自己体会,我就纳闷,为啥设置一个固定值,这样到了手机不就很大了吗,直到我跑起来之后,emmmmm
head() {
return {
title: 'sob文章详情',
meta: [
{
hid: 'viewport',
name: 'viewport',
content: 'width=device-width,initial-scale=1.0'
}
]
}
}
完整的代码
<template>
<div id="app">
<div class="container">
<div class="markdown-body sob-article-content" v-html="article_content">
</div>
</div>
</div>
</template>
<script>
import * as api from './api/api'
// 代码高亮
// 其他元素使用 github 的样式
import 'github-markdown-css'
import 'highlight.js/styles/default.css'
import hljs from 'highlight.js'
const highlightCode = () => {
const preEl = document.querySelectorAll('pre')
preEl.forEach((el) => {
hljs.highlightBlock(el)
})
}
export default {
name: 'App',
created() {
const url = window.location.href;
console.log("获取完整url:" + url);
const para = url.split('?')[1];
console.log("获取第一个参数:" + para);
this.articleId = para.split('=')[1];
console.log("获取数值 " + this.articleId);
},
data() {
return {
article_content: '',
articleId: '',
}
},
head() {
return {
title: 'sob文章详情',
meta: [
{
hid: 'viewport',
name: 'viewport',
content: 'width=device-width,initial-scale=1.0'
}
]
}
},
mounted() {
this.httpGetArticle();
highlightCode();
},
methods: {
httpGetArticle() {
//1422385783846830082 1411666843780882434
api.getArticleDetail2(this.articleId).then(resp => {
if (api.success_code === resp.code) {
this.article_content = resp.data.content;
}
});
}
},
updated() {
highlightCode();
},
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: left;
color: #2c3e50;
margin-top: 10px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 750px;
min-height: 600px;
width: 100%;
margin: 0 auto;
padding: 20px 20px;
background-color: white;
}
.image-wrap img {
max-width: 100%;
}
.sob-article-content {
max-width: 100%;
}
.sob-article-content pre code {
max-width: 100%;
}
/*img 设置max-width有效*/
.sob-article-content img {
margin-top: 10px;
max-width: 100%;
cursor: zoom-in;
}
/* 大于等于750px作用,同理max-width为小于等于下作用 不同屏幕的特殊处理,下面是例子 */
@media (min-width: 750px) {
.title {
font-size: 24px;
}
}
@media (max-width: 750px) {
.summary {
font-size: 14px;
}
}
</style>
总结
1、就是有手就行
2、前端不会,就只能问下朋友,Google一下,慢慢摸索
3、之前学习过康师傅前端,有一点认识
4、网络请求,数据显示这部分不难,主要是如何适配手机
5、就是我朋友给我的代码加上那句媒体查询,剩下都是查回来的
6、这个是加载了内容区,剩下的自己可以加头像,个人信息,评论什么的,动手就行了
一个诡异的地方,如果我只是简单使用hljs高亮代码,代码会超越限制的750px,无法适配,后来我不知道在哪里查到markdown-body
这个组件,然后配合
import 'github-markdown-css'
就做好了宽度的限制,如果有前端大佬,可以科普下,感谢、
整个过程的重点就是一个字:查,各种查,然后尝试。。。。。。我太菜了[菜狗]
如何给手机用?
不知道上面的代码中,是否留意到了这里vue.config.js
module.exports = {
//打包到手机上面跑,需要做资源路径定位,下面这个代码处理
publicPath : './',
devServer: {
}
}
这是我查回来,不同cli版本打包给手机使用不同的,重点是资源的定位问题publicPath
还是老样子,直接点击build打包,得到dist中的文件,放到安卓的asset目录中,如果没有这个目录,创建一个就行。给出我的例子
webView.loadUrl("file:///android_asset/vue/index.html?id="+ id)
这样就可以本地加载文章了,当然也可以发布到自己的服务器中,做一个开关,当需要切换远程的时候就切过来就行了,这样方便在线改需求(修复bug)
比如我部署的:传送门点击 地址就是http://api.moonlightshadow.cn/?id=康师傅api提供文章id,如果你想白嫖,直接用这个地址就行了。
希望大家都可以写出属于自己的沙滩,拿着它摸鱼也好,面试也行。
这是我写的阳光沙滩的手机端效果。
体验下载地址点我下载