创建Vue项目流程
一、创建vue项目
-
vue CLI 基于webpack
vue create 项目名 -
create vue 基于vite
npm init vue@latest
二、项目基本配置
-
icon 配置图标
public / favicon.ico
-
标题
index.html / title
-
jsconfig.json(友好的代码提示)
三、目录结构的划分
四、重置样式
-
安装normalize.css 在main.js中引入
npm install --save normalize.css main.js import "normalize.css" -
assets/css/reset.css
body,h1,h2,h3,h4,ul,li{ padding: 0; margin: 0; } ul,li{ list-style: none; } a{ text-decoration: none; color: #333; } img{ vertical-align: top; } -
assets/css/common.css
body{ font-size: 14px; } -
assets/css/index.css
@import "common.css"; @import "reset.css"; -
main.js
import "normalize.css" import "@/assets/css/index.css"
五、配置路由
-
安装路由
npm install vue-router -
配置路由 router/index.js
import {createRouter, createWebHashHistory} from "vue-router"; const router = createRouter({ history: createWebHashHistory(), //配置映射关系 routes: [ { path: '/', redirect: '/home' //重定向 }, { path: '/home', component: () => import('@/views/home/Home.vue') }, { path: '/favor', component: () => import('@/views/favor/Favor.vue') }, { path: '/order', component: () => import('@/views/order/Order.vue') }, { path: '/message', component: () => import('@/views/message/Message.vue') } ] }) export default router -
main.js中使用
import router from "@/router" app.use(router) -
在需要使用的地方
<router-view/> <router-link to="/home">首页</router-link> <router-link to="/favor">收藏</router-link> <router-link to="/order">订单</router-link> <router-link to="/message">消息</router-link>
六、状态管理
-
安装pinia
npm install pinia -
store/index.js
import {createPinia} from "pinia"; const pinia = createPinia() export default pinia -
store/modules/city.js
import {defineStore} from "pinia"; const useCityStore = defineStore('city',{ state:()=>({ cities:[] }), actions:{ } }) export default useCityStore() -
main.js
import pinia from "@/stores"; app.use(pinia)
七、UI组件库(vant)
1、vant官网
vant-ui.github.io/vant/#/zh-C…
2、vant使用
查看官网(介绍、快速上手)
3、修改第三方UI组件库的样式
- 若是用插槽,插入了自己的元素,那么在自己的作用域中直接修改这个元素
- 全局定义一个变量,覆盖它默认变量的值,但是缺点是全局修改
- 局部定义一个变量,覆盖它默认变量的值
- 直接查找对应的子组件选择器,进行修改,:deep(子组件中元素的选择器)进行修改,直接修改的是css
4、使用UI组件库场景
-
类型一:后台管理系统
Element-UI(vue2) / Element-Plus(vue3)
-
类型二:小程序
小程序原生UI库 / Vant
-
类型三:移动端Web页面
Vant UI
-
类型四:网易云/知乎/Bilibili
Element-Plus
八、tabBar隐藏
1、通过路由隐藏
router/index.js
{
path: '/city',
component: () => import('@/views/city/City.vue'),
meta:{
hideTabBar:true
}
},
App.vue
<TabBar v-if="!route.meta.hideTabBar"/>
import {useRoute} from "vue-router";
const route = useRoute()
2、通过class隐藏
common.css
.hideTabBar{
position: relative;
z-index: 9;
height: 100vh;
overflow-y: auto;
background: #fff;
}
九、servers
使用axios二次封装来进行网络请求
网络请求,如果直接在组件内部进行请求的话,若有一天URL地址变了不好维护,所以对网络请求还进行二次封装
文件夹结构:
但是如果直接在组件内发送网络请求有两个缺点:
1.如果请求太多,那么页面组件中就包含大量对于网络请求和数据的处理逻辑
2.如果页面封装了很多的子组件,子组件需要这些数据,还需要一步一步将数据传过去
所以采用pinia存储数据
stores/modules/city.js
import {defineStore} from "pinia";
import {getCityRequest} from "@/services";
const useCityStore = defineStore('city', {
state: () => ({
citiesData: {}
}),
actions: {
async fetchCitiesData() { //发送网络请求 请求过来的数据保存在state中 组件用的话直接取
const res = await getCityRequest()
this.citiesData = res.data
}
}
})
export default useCityStore
City.vue
const cityStore = useCityStore()
cityStore.fetchCitiesData()
const {citiesData} = storeToRefs(cityStore)
十、页面请求数据
发送axios 请求分页数据,民宿项目中,请求houstlist数据(codercba.com:1888/api/home/ho…
export function getHomeHoustList(currentPage) {
return AxiosRequest.get({
url: '/home/houselist',
params: {
page: currentPage
}
})
}
请求分页数据时,使用currentPage来记录当前页,把currentPage存在pinia中
import {defineStore} from "pinia";
import {getHomeCategories, getHomeHotSuggests, getHomeHoustList} from "@/services";
const useHomeStore = defineStore('home', {
state: () => ({
currentPage:1,
houstList:[]
}),
actions: {
async fetchHomeHouseList() {
const res = await getHomeHoustList(this.currentPage)
this.houstList.push(...res.data)
this.currentPage++
}
}
})
export default useHomeStore
每当发送一次请求时,currentPage都++
十一、监听页面滚动到底部
监听:什么时候页面滚动到了底部
页面为什么会滚动
1.window窗口滚动
2.元素滚动:overflow-y:auto
hooks
import {onMounted, onUnmounted, ref} from "vue";
import {throttle} from "underscore";
//方法一:传入回调函数来判断是否到达底部
// export default function (reachBottom){
// //监听window滚动
// const scrollListenerHandler = ()=>{
// const clientHeight = document.documentElement.clientHeight
// const scrollTop = document.documentElement.scrollTop
// const scrollHeight = document.documentElement.scrollHeight
// // console.log(clientHeight, scrollTop, scrollHeight)
// if (clientHeight + scrollTop + 1 >= scrollHeight) {
// if(reachBottom) reachBottom()
// }
// }
// onMounted(()=>{
// window.addEventListener('scroll', scrollListenerHandler)
// })
// onUnmounted(()=>{
// window.removeEventListener('scroll',scrollListenerHandler)
// })
// }
//方法二:通过变量来监听是否滚动到底部
//防抖、节流 (使用节流)
export default function () {
const isReachBottom = ref(false)
const clientHeight = ref(0)
const scrollTop = ref(0)
const scrollHeight = ref(0)
//监听window滚动
const scrollListenerHandler = throttle(() => {
clientHeight.value = document.documentElement.clientHeight
scrollTop.value = document.documentElement.scrollTop
scrollHeight.value = document.documentElement.scrollHeight
// console.log(clientHeight, scrollTop, scrollHeight)
if (clientHeight.value + scrollTop.value + 1 >= scrollHeight.value) {
isReachBottom.value = true
}
}, 100)
onMounted(() => {
window.addEventListener('scroll', scrollListenerHandler)
})
onUnmounted(() => {
window.removeEventListener('scroll', scrollListenerHandler)
})
return {isReachBottom, clientHeight, scrollTop, scrollHeight}
}
监听滚动
//监听滚动到底部
//方法一
// useScroll(()=>{
// homeStore.fetchHomeHouseList()
// })
//方法二
const {isReachBottom, scrollTop} = useScroll()
watch(isReachBottom, (newValue) => {
if (newValue) {
homeStore.fetchHomeHouseList().then(() => {
isReachBottom.value = false
})
}
})
// const isShowSearchBar = ref(false)
// watch(scrollTop, (newValue) => {
// isShowSearchBar.value = newValue > 100
// })
//定义的可响应式数据,依赖另外一个可响应式的数据,那么可以使用计算属性(computed)
const isShowSearchBar = computed(()=>{
return scrollTop.value >= 360
})
十二、loading显示
从服务器获取数据时,当数据还没有加载完毕时,给用户显示出一个loading样式
将loading放入pinia仓库main.js中,设置isLoading:false
每次向服务器发送请求时,都会来到request/index.js中
import axios from 'axios'
import { BASE_URL, TIMEOUT } from './config'
import useMainStore from "@/stores/modules/main";
const mainStore = useMainStore()
class AxiosRequest {
constructor(baseURL, timeout=10000) {
this.instance = axios.create({
baseURL,
timeout
})
// 拦截器实现isloading
this.instance.interceptors.request.use(config => {
mainStore.isLoading = true
return config
}, err => {
return err
})
this.instance.interceptors.response.use(res => {
mainStore.isLoading = false
return res
}, err => {
mainStore.isLoading = false
return err
})
}
request(config) {
// mainStore.isLoading = true
return new Promise((resolve, reject) => {
this.instance.request(config).then(res => {
// mainStore.isLoading = false
resolve(res.data)
}).catch(err => {
// mainStore.isLoading = false
reject(err)
})
})
}
get(config) {
return this.request({ ...config, method: "get" })
}
post(config) {
return this.request({ ...config, method: "post" })
}
}
export default new AxiosRequest(BASE_URL, TIMEOUT)
十三、点击热门精选跳转到房屋详情页
- 监听item点击(在HouseList.vue中,在组件上写@click事件,传入同一个点击事件,不用写重复代码)
- 跳转到详情页
- 携带对应的参数houseId
使用动态路由来传递参数
{
path: '/detail/:id',
component: () => import('@/views/detail/Detail.vue')
}
十四、地图显示
百度地图开放管理 ---> 控制台 ---> AK ---> 官方文档 ---> 使用
十五、tabControl
- 开发tabcontrol
- 监听滚动
- 滚动到一定位置,显示出来
- 监听tabcontrol点击,点击之后滚动到正确的位置
需求:页面滚动,滚动到一定位置时,显示正确的tabCOntrol的索引(标题),和歌词匹配是一个算法
- 监听滚动的位置 scrollTop
- 利用scrollTop去匹配正确的位置
十六、px转换vw
vite/webpack ---> postcss工具 ---> plugins ---> postcss-px-to-viewport
<注>:本人是学习coderwhy老师的项目,项目接口均来自coderwhy老师,如有想学习coderwhy老师的课程,请前往腾讯课堂。本篇文章是自己总结的流程,望周知。