vue3-vite2-blog-h5
一款简洁版本的挪动端博客。前端我的项目次要是采纳 Vue3
最新语法糖 <script setup>
和Vant3.0
来搭建的;采纳 Tsx
来渲染公共组件;采纳 Vite2.0
来构建、打包。后端我的项目次要采纳 Node
框架 Koa2
以及 MongoDB
数据库来设计的。
- PC 端博客线上预览地址:http://www.rasblog.com
- PC 端博客仓库地址:https://github.com/Sujb-sus/vue-node-mongodb-blog
- H5 端博客仓库地址:https://github.com/Sujb-sus/vue3-vite2-ts-blog-h5
我的项目预览
我的项目构造
技术使用
一、rem 适配
- 装置插件
yarn add amfe-flexible postcss-pxtorem -S
amfe-flexible
是配置可伸缩布局计划,次要是将 1 rem 设为 viewWidth / 10postcss-pxtorem
是 postcss 的插件,用于将像素(px)单元生成 rem 单位
- 在 main.ts 导入
amfe-flexible
import "amfe-flexible";
- 在
postcss.config.js
配置postcss-pxtorem
module.exports = {
plugins: {
"postcss-pxtorem": {
rootValue: 37.5,
propList: ["*"],
},
},
};
- rootValue 依据设计稿宽度除以 10 进行设置,这边假如设计稿为 375,即 rootValue 设为 37.5
- propList 是设置须要转换的属性,这边 * 意思就是为所有单位为(px)都进行转换
二、增加 css 前缀
- 装置插件
yarn add autoprefixer -D
- 在
postcss.config.js
配置autoprefixer
module.exports = {
plugins: {
autoprefixer: {overrideBrowserslist: ["Android 4.1", "iOS 7.1"],
grid: true,
},
},
};
- overrideBrowserslist:浏览器的兼容配置
- grid: true 为 IE 启用网格布局前缀
三、公共组件用 tsx 语法编写
// svgIcon.tsx
import {defineComponent, computed} from "vue";
export default defineComponent({
name: "svgIcon",
props: {
name: {
type: String,
required: true,
},
},
setup(props) {const iconName = computed(() => `#${props.name}`);
return () => (
<>
<svg class="icon" aria-hidden="true">
<use xlinkHref={iconName.value}></use>
</svg>
</>
);
},
});
- defineComponent 对 setup 函数进行封装,返回 options 的对象,在 ts 下给予了组件正确的参数类型推断
<use xlink:href={iconName.value}>
须要改为驼峰模式<use xlinkHref={iconName.value}>
,不然会有语法问题
四、用 <script setup>
语法糖
1. 父组件传值给子组件
<!-- 父组件的 html -->
<List :showTitle="false" :params="params"></List>
// 子组件的 <script setup>
interface Props {
showTitle?: boolean;
params?: object;
}
const props = withDefaults(defineProps<Props>(), {
showTitle: true,
params: undefined,
});
defineProps
定义 props 类型withDefaults
提供 props 默认值- 两者在
<script setup>
内不须要额定导入即可应用
2. 子组件传值给父组件
<!-- 父组件的 html -->
<LabelSelect @changeLabel="changeLabel" ref="label"></LabelSelect>
// 父组件的 <script setup>
const changeLabel = (labelName: string) => {params.type = labelName;};
// 子组件的 <script setup>
const emit = defineEmits(["changeLabel"]);
emit("changeLabel", labelName);
defineEmits
定义响应父组件的办法名,须要先定义才可通过 emit()响应emit('changeLabel', data)
,changeLabel 为响应的办法名,labelName 就是要传给父组件的值
3. 逻辑复用
- 用 use… 以驼峰的模式结尾定义文件,定义一个 useClickLike 函数且导出;
// useClickLikes.ts
import {ref, computed} from "vue";
function useClickLike(requestApi: Function) {let currentId = ref(""); // 以后 id
let isLike = ref(false); // 是否点赞
let likeList = ref<string[]>([]); // 点过赞列表
const handleLikes = (id: string) => {if (likeList.value.includes(id)) {
isLike.value = true;
likeList.value.splice(likeList.value.indexOf(id), 1);
} else {
isLike.value = false;
likeList.value.push(id);
}
currentId.value = id;
return requestApi({_id: id, isLike: isLike.value}).catch((err: any) => {console.log(err);
});
};
return {handleLikes,};
}
export default useClickLike;
- 在 vue 文件中援用,先导入进来,再解构出所须要的函数逻辑
import useClickLike from "@/useMixin/useClickLike";
// 点赞逻辑
const {handleLikes} = useClickLike(apiUpdateLikes);
- handleLikes 就能够在 html 模版间接使用
<div class="footer-item" @click.stop="handleLikes(item._id)"></div>
4. computed、watch 的应用
import {computed, watch} from 'vue'
const getLikesNumber = computed(() => (id: string, likes: number) =>
likeList.value.includes(id) ? likes + 1 : likes
);
watch(props.params, (newVal,oldVal) => {
pageindex.value = 1
hasLoad.value = false
loading.value = false
finished.value = false
list.value = []
getBlogList()})
- computed 语法跟 vue2 一样,watch 语法有略微不同,props.params 为监听对象,newVal 为监听到的最新值,oldVal 为旧值
- 具体语法可参看官网文档:https://v3.cn.vuejs.org/api/computed-watch-api.html#computed
5. vuex 的应用
import {useStore} from "vuex";
const store = useStore();
// 获取 label 模块 actions 下的 getLabelList 办法
const getLabelList = () => store.dispatch("label/getLabelList");
getLabelList(); // 间接执行办法
// 获取 label 模块 getters 下的 labelList 属性
const labelList = store.getters["label/labelList"];
- 其余具体用法请参考官网文档:https://next.vuex.vuejs.org/zh/guide/modules.html
6. vue-router 的应用
- 配置路由文件,
createWebHashHistory
制订 hash 模式 /:pathMatch(.*)*
匹配所有路由做重定向用- 导入路由文件须要用
import.meta.glob
,不能用间接用import
导入,import
在开发时没问题,然而在打包后的文件会辨认不了路由文件
import {createRouter, createWebHashHistory, RouteRecordRaw} from "vue-router";
import Tabbar from "../components/tabbar";
// 先辨认所有的 views/ 文件夹 name/*.vue 文件
// 这里限制性很高,只有门路为 /views/ 文件夹 name/*.vue,的文件能力背辨认
const modules = import.meta.glob("../views/*/*.vue");
const loadComponent = (component: string) =>
modules[`../views/${component}.vue`];
const routes: Array<RouteRecordRaw> = [
{
path: "/home",
component: loadComponent("home/index"),
meta: {title: "首页",},
},
....
{path: "/:pathMatch(.*)*",
redirect: "/home",
},
];
const router = createRouter({history: createWebHashHistory(),
routes,
});
export default router;
- 获取路由携带的 query 参数
import {useRouter} from "vue-router";
const route = useRouter();
const id = route.currentRoute.value.query["id"];
后端服务
必须得先开启后端服务接口,连贯上 MongoDB
数据库,不然前端我的项目没法预览。这边的服务接口其实是复用了 PC 端 wall-blog
我的项目的接口。所以如果想要在治理后盾增加数据的,须要移至该仓库:https://github.com/Sujb-sus/vue-node-mongodb-blog。
该仓库下共有三个我的项目,PC 治理端(admin)、PC 客户端(client)、后盾服务端(server)。server
我的项目其实就是本我的项目的 server
目录,为了不便大家的预览,我 Copy 了一份过去。
- client:博客的 PC 端
- admin:博客的治理端,就是用来增加文章数据、标签数据等等
- server:给博客提供接口服务数据
开启后端接口服务
形式一、移至上述所说的仓库地址
该仓库下有具体的形容,次要流程如下:
- 查看注意事项,先装置、连贯好本地的
MongoDB
数据库,开启服务 - 启动
admin
我的项目,就能够通过治理后盾手动增加数据了
形式二、间接在本我的项目连贯 MongoDB
数据库
- 我的项目启动前,须要在本地装置好
MongoDB
数据库; - 在
server/config.js
文件配置数据库名、用户以及明码等一些必要的信息;这些信息都能够自定义,然而须要跟步骤 3
同步起来;
// server/config.js
export default {
env: process.env.NODE_ENV,
port,
auth,
log,
mongodb: {
username: "wall", // 数据库用户
pwd: 123456, // 数据库明码
address: "localhost:27017",
db: "wallBlog", // 数据库名
},
};
- 启动本地的
mongo
服务,给数据库初始化在server/config.js
配置的一些必要信息;
> mongo // 开启 mongo 服务
> show dbs // 显示数据库列表
> use wallBlog // 新建一个 wallBlog 数据库
> db.createUser({user:"wall",pwd:"123456",roles:[{role:"readWrite",db:'wallBlog'}]}) // 在 wallBlog 数据库创立一个 wall 用户,明码为 123456
> show users // 展现该库有哪些用户
> db.auth("wall", "123456"); // 数据库认证一下用户、明码,返回 1 认证胜利
- 进入
server
目录,装置依赖,并开启服务
cd server // 进入 server 目录
yarn // 装置依赖包
yarn server // 开启后端接口,胜利了便会提醒数据库连贯胜利
注意事项
env.d.ts
文件:用 ts 写的模块在公布的时候依然是用 js 公布,所以须要一个 d.ts 文件来标记某个 js 库外面对象的类型models/index.ts
文件:用来定义接口返回的数据的类型,每个数据的类型都须要定义,不然在打包 vue 文件的 html 渲染数据时会有问题;导出须要用export type {...}
格局导出components/noData.tsx
文件:援用动态图片时,须要用模块导入的模式导入进来,间接在 html 应用图片门路在打包时,不会主动解析该图片门路styles/common/iphone_x.scss
文件:提供了适配 iPhonex 全面屏系列的底部间距tsconfig.json
文件:strict:true 开启所有严格类型查看
参考文档
- ts 中文文档:https://www.tslang.cn/docs/handbook/compiler-options.html
- vite 中文文档:https://cn.vitejs.dev/config/