项目终于完整做完了!!! 现在总结一下笔记
在做项目的过程中,做了一些笔记,记录了自己有疑问的地方,还要一个个解决,现在先写一下每个项目开始前的准备:
创建vue实例
Vue实例对象 Vue()是一个构造函数,用new Vue(构造参数)得到的就是一个实例对象,Vue实例对象是Vue.js中最基本的单元。构造参数是一个对象,构造参数的属性即为参数选项,常见的参数选项有el、data、template、components等。
vue3的创建app实例和挂载方法:
App.vue
代码语言:javascript复制<template>
<div class="container">
我是根组件
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
main.js
代码语言:javascript复制// 创建一个vue应用
// 1. 导入createApp函数
// 2. 编写一个根组件App.vue,导入进来
// 3. 基于根组件创建应用实例
// 4. 挂载到index.html的#app容器
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
mount()方法就是挂载到某个html的DOM节点上,它接受一个字符串型参数,参数可以使用CSS选择器,一般都是ID选择器的形式,指定挂载的DOM元素。
本文由“壹伴编辑器”提供技术支持
mvvm设计模式讲解
Vue的编程设计模式应该叫做mvvm
的设计模式。什么叫做mvvm
呢?它首先是面向数据的编程,程序中定义了数据,然后定义了模板,Vue
就可以把数据和模板自动进行关联。最后挂载到真实的DOM
上,展示给用户。
mvvm解释: 第一个
m
代表model
数据,第一个v
代表view
视图,最后两个字母vm
代表viewModel
视图数据连接层。
如果还不太明白,我们可以看一下Demo.html进行理解。
代码语言:javascript复制
代码语言:javascript复制<script>
const app = Vue.createApp({
data() {
return {
message: 'mybj123.com' //1.在这里定义了数据,也就是`model`数据
}
},
template: "<h2>{{message}}</h2>" //2.在这里定义了模板,也就是`view`,
//定义后的自动关联,就叫做`vm`,viewModel数据视图连接层。
})
const vm = app.mount("#app")
console.log(vm)</script>
代码语言:javascript复制
model
数据,是我们自己定义的,view
模板也是我们自己定义的,但是vm
是Vue自动给我们关联的。
本文由“壹伴编辑器”提供技术支持
本文由“壹伴编辑器”提供技术支持
jsconfig.json
这个代码是让我们在导入文件的时候直接从src开始找文件, '@/'就进入了src目录
代码语言:javascript复制{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
}
},
"exclude": ["node_modules", "dist"]
}
本文由“壹伴编辑器”提供技术支持
modules (分模块)
有时候我们的项目很大,涉及的数据很多,这个时候就要分模块,做好分类,分模块是怎么使用的呢?
现在index中导入各个模块, 写在modules中
index.js
要怎么使用modules里面的数据呢?不能和以前一样直接store.state.xxx, 因为每个不同的modules里面都有state,那怎么拿到我们想要的模块中的数据呢
看看cart里面的state数据:
cart.js
我尝试在页面中打印$store.state, 看看里面都是什么
使用json转换工具转换的结果
调用store的state数据方法:
由于我们是使用了模块化的方式,调用最外层的state中的数据 依然是
store.state.模块名.返回的数据
调用mutations或者是actions中的方法:
namespace命名空间注意点:由于是没有对模块进行命名空间的,所以默认在使用 this.$store.commit/dispatch() 在提交方法的时候,会对所有状态管理的actions和mutations中的方法进行匹配,这就导致了一个问题,就是当不同模块之间的方法命名一样的情况下,会造成方法同时调用的问题
这个时候,我们需要在定义模块的时候,添加上 namespaced:true 属性
store.dispatch/commit("模块名/方法");
本文由“壹伴编辑器”提供技术支持
vuex持久化
目的:让在vuex中管理的状态数据同时存储在本地。可免去自己存储的环节。
- 在开发的过程中,像用户信息(名字,头像,token)需要vuex中存储且需要本地存储。
- 再例如,购物车如果需要未登录状态下也支持,如果管理在vuex中也需要存储在本地。
方法:
- 首先:我们需要安装一个vuex的插件vuex-persistedstate来支持vuex的状态持久化。
- 在index导入不同的模块
- 在index.js中写如下代码:
import { createStore } from 'vuex'
import createPersistedstate from 'vuex-persistedstate'
import user from './modules/user'
import cart from './modules/cart'
import category from './modules/category'
export default createStore({
modules: {
user,
cart,
category
},
plugins: [
createPersistedstate({
key: 'erabbit-client-pc-store',
//下面写数据需要持久化的模块名
paths: ['user', 'cart']
})
]
})
===> 默认是存储在localStorage中
===> key是存储数据的键名
===> paths是存储state中的那些数据,如果是模块下具体的数据需要加上模块名称,如user.token
===> 修改state后触发才可以看到本地存储数据的的变化。
本文由“壹伴编辑器”提供技术支持
请求工具
- npm i axios
- 新建 src/utils/request.js 模块,代码如下
// 1. 创建一个新的axios实例
// 2. 请求拦截器,如果有token进行头部携带
// 3. 响应拦截器:1. 剥离无效数据 2. 处理token失效
// 4. 导出一个函数,调用当前的axsio实例发请求,返回值promise
import axios from 'axios'
import store from '@/store'
import router from '@/router'
// 导出基准地址
export const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net'
//export const baseURL = 'https://apipc-xiaotuxian-front.itheima.net'
const instance = axios.create({
// axios 的一些配置,baseURL timeout
baseURL,
timeout: 5000
})
instance.interceptors.request.use(config => {
// 拦截业务逻辑
// 进行请求配置的修改
// 如果本地又token就在头部携带
// 1. 获取用户信息对象
const { profile } = store.state.user
// 2. 判断是否有token
if (profile.token) {
// 3. 设置token
config.headers.Authorization = `Bearer ${profile.token}`
}
return config
}, err => {
return Promise.reject(err)
})
instance.interceptors.response.use(
// res => res.data 取出data数据,将来调用接口的时候直接拿到的就是后台的数据
res => res.data,
err => {
// 401 状态码,进入该函数
if (err.response && err.response.status === 401) {
// 1. 清空无效用户信息
// 2. 跳转到登录页
// 3. 跳转需要传参(当前路由地址)给登录页码
store.commit('user/setUser', {})
// 当前路由地址
// 组件里头:`/user?a=10` $route.path === /user $route.fullPath === /user?a=10
// js模块中:router.currentRoute.value.fullPath 就是当前路由地址,router.currentRoute 是ref响应式数据
const fullPath = encodeURIComponent(router.currentRoute.value.fullPath)
// encodeURIComponent 转换uri编码,防止解析地址出问题
router.push('/login?redirectUrl=' fullPath)
}
return Promise.reject(err)
})
// 请求工具函数
export default (url, method, submitData) => {
// 负责发请求:请求地址,请求方式,提交的数据
return instance({
url,
method,
// 1. 如果是get请求 需要使用params来传递submitData ?a=10&c=10
// 2. 如果不是get请求 需要使用data来传递submitData 请求体传参
// [] 设置一个动态的key, 写js表达式,js表达式的执行结果当作KEY
// method参数:get,Get,GET 转换成小写再来判断
// 在对象,['params']:submitData ===== params:submitData 这样理解
[method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
})
}
本文由“壹伴编辑器”提供技术支持
设计路由:
本文由“壹伴编辑器”提供技术支持
less自动化导入:
目的: 准备常用less变量,混入代码,完成自动导入。less混入就是声明一段css代码(选择器包裹的代码)或者函数(如下面的就直接.hoverShadow()即可调用这个函数的方法),在其他css选择器调用,可复用包裹的代码。
方法:
1.准备需要自动化导入的 less 文件
2.下载插件
3.添加配置自动化导入的相关配置
4.重启开发服务器
变量文件:
src/assets/styles/variables.less
代码语言:javascript复制// 主题
@xtxColor:#27BA9B;
// 辅助
@helpColor:#E26237;
// 成功
@sucColor:#1DC779;
// 警告
@warnColor:#FFB302;
// 价格
@priceColor:#CF4444;
混入文件
src/assets/styles/mixins.less
代码语言:javascript复制// 鼠标经过上移阴影动画
.hoverShadow () {
transition: all .5s;
&:hover {
transform: translate3d(0,-3px,0);
box-shadow: 0 3px 8px rgba(0,0,0,0.2);
}
}
在当前项目下执行一下命令vue add style-resources-loader,添加一个vuecli的插件,如遇警告,按'y'即可, 选择预处理器
安装完毕后会在vue.config.js中自动添加配置,如下:
代码语言:javascript复制module.exports = {
// ... 其他配置
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: []
}
}}
代码语言:javascript复制 把你需要注入的文件配置一下后,重启服务即可。
代码语言:javascript复制 const path = require('path')
module.exports = {
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
path.join(__dirname, './src/assets/styles/variables.less'),
path.join(__dirname, './src/assets/styles/mixins.less')
]
}
}
}
本文由“壹伴编辑器”提供技术支持
样式重置与公用
如果我们有一些公共样式呀使用,就在main.js中导入样式,例如normalize.css,可以npm i normalize.css,然后在main.js中直接import 'normalize.css'就可以使用了,但是如果是自己写的文件,那么就要用import '@/assets/styles/common.less'这种导入方式
这些就是在项目开始前需要做的一些准备,后面再写遇到的问题和疑难点,发现自己还是有很多基础不牢