一、项目介绍
- 优选商城pc端
- 旅途移动端web项目(H5)
- 后台管理系统 ts + vue3
常见前端项目的UI库
后台管理系统:element UI 、Ant-Design
小程序:vant
移动端web:vant
门户网站:局部引入UI库
海外:Material UI 规范 react\mui,vue\vuetify
二、项目实战
1.创建项目
方式一:Vue CLI
- 基于webpack工具
- 命令: vue create
方式二: create-vue
- 基于vite工具
- 命令:npm init vue@latest
项目配置
- 配置项目的icon
- 配置项目的标题
- 配置jsconfig.json
2.项目目录结构划分
src
|-assets -- 存放静态资源,比如css/images/font等
|-components -- 存放公共组件
|-composables -- 组合式函数
|-mock -- 模拟测试数据
|-router -- 路由
|-services -- 接口
|-stores -- 状态管理,比如pinia、vuex
|-utils -- 工具包
|-views -- 页面
|-App.vue
|-main.js
|-gitignore
|-index.html
|-jsconfig.json
|-package-lock.json
|-package.json
|-README.md
|-vite.config.js
3.CSS样式重置
对默认CSS样式进行重置:
- normalize.css
- reset.css
npm i normalize.css --save
main.js
import 'normalize.css'
assets/css/reset.css
/* 自定义的css */
a {
text-decoration: none;
color: #333;
}
assets/css/index.css
/* 作为css文件的入口统一导入 */
@import './reset.css';
@import './common.css';
4.路由配置
router/index.js
import {createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: 'home',
component: () => import('@/views/home/index.vue'),
},
],
})
export default router
main.js
import { createApp } from 'vue'
import pinia from './stores'
import App from './App.vue'
import router from './router'
import 'normalize.css'
import '@/assets/css/index.css'
const app = createApp(App)
app.use(router)
app.mount('#app')
5.状态管理配置
stores/index.js
import {createPinia} from "pinia";
const pinia = createPinia()
export default pinia
stores/modules/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++
},
},
})
三、开发中会遇到的问题
1.修改第三方UI组件库的样式
1.用插槽,插入自己的元素那么在自己的作用域中直接修改这个元素
2.全局定义一个变量,覆盖它默认变量的值 *缺点: 全局修改
3.局部定义一个变量,覆盖它默认变量的值 !优点: 局部修改
4.直接查找对应的子组件选择器,进行修改:deep(子组件中元素的选择器)进行修改直接修改CSS
2.vite中动态加载图片
const getAssetUrl = (image) => {
// 参数一: 相对路径
// 参数二: 当前路径的url
const url = `../assets/images/${image}`;
return new URL(url, import.meta.url).href;
};
3.tabs选项与滚动内容匹配算法
该算法同样适用于歌词匹配
const titlePositionMap = {
'设施': 300,
'房东': 500,
'评论': 700,
'须知': 1000,
}
// 当前滚动高度
let newValue = 424;
const offsetTopArr = Object.values(titlePositionMap);
let currentIndex = offsetTopArr.length - 1;
// 遍历tabs每个选项的高度,找到当前高度所在的选项索引值
for (let i = 0; i < offsetTopArr.length; i++) {
if (newValue + 44 < offsetTopArr[i]) {
currentIndex = i - 1;
break;
}
}
tabRef.value.currentIndex = currentIndex < 0 ? 0 : currentIndex;
4.集成百度地图SDK
1.注册百度账号,登录百度地图开发平台
2.打开控制台>应用管理>我的应用,点击创建应用
3.输入应用名称,选择浏览器端,点击确认
4.复制访问应用的ak用于后续的接口调用
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title>Vite App</title>
<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=3.0&&type=webgl&ak=[输入复制的ak]"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
map.vue
<template>
<div class="baidu" ref="mapRef"></div>
</template>
<script setup>
const mapRef = ref()
const position = {
longitude: 112.333,
latitude: 52.343
}
onMounted(() => {
const map = new BMapGL.Map(mapRef.value); // 创建地图实例
const point = new BMapGL.Point(position.longitude, position.latitude); // 创建点坐标
map.centerAndZoom(point, 15); // 初始化地图,设置中心点坐标和地图级别
const marker = new BMapGL.Marker(point);
map.addOverlay(marker)
})
</script>
5.组合式函数
在项目中一些公共人物的逻辑可以封装成一个组合式函数进行复用,比如监听页面滚动函数:
useScroll.js
import { throttle } from 'underscore'
export default function useScroll (elRef) {
let el = window;
const reachBottom = ref(false);
const clientHeight = ref(0)
const scrollTop = ref(0)
const scrollHeight = ref(0)
// 节流操作
const loadMoreHandler = throttle(() => {
if (el === window) {
clientHeight.value = document.documentElement.clientHeight;
scrollTop.value = document.documentElement.scrollTop;
scrollHeight.value = document.documentElement.scrollHeight;
} else {
clientHeight.value = el.clientHeight;
scrollTop.value = el.scrollTop;
scrollHeight.value = el.scrollHeight;
}
if (scrollHeight.value - scrollTop.value <= clientHeight.value) {
reachBottom.value = true
}
}, 100)
onMounted(() => {
if (elRef) {
el = elRef.value;
}
el.addEventListener("scroll", loadMoreHandler)
})
onActivated(() => {
el.addEventListener("scroll", loadMoreHandler)
})
onUnmounted(() => {
el.removeEventListener("scroll", loadMoreHandler)
})
onDeactivated(() => {
el.removeEventListener("scroll", loadMoreHandler)
})
return {
reachBottom,
clientHeight,
scrollTop,
scrollHeight,
}
}
6.vue中的函数模板引用
在vue中需要直接访问底层 DOM 元素时,不仅仅可以使用ref字符串作为名字,还可以使用函数
<script setup>
const bindRef = (el) => {
console.log(el);
el.addEventListener('click', () => {})
}
</script>
<template>
<input :ref="bindRef" />
</template>
注意我们这里需要使用动态的
:ref
绑定才能够传入一个函数。当绑定的元素被卸载时,函数也会被调用一次,此时的el
参数会是null
。