赞
踩
开发一个前端模块可以概括为以下几个步骤:
(1)写静态页面、拆分为静态组件;
(2)发请求(API);
(3)vuex(actions、mutations、state三连操作);
(4)组件获取仓库数据,动态展示;
public文件夹:静态资源,webpack进行打包的时候会原封不动打包到dist文件夹中。
pubilc/index.html是一个模板文件,作用是生成项目的入口文件,webpack打包的js,css也会自动注入到该页面中。我们浏览器访问项目的时候就会默认打开生成好的index.html。
src文件夹(程序员代码文件夹)
assets: 存放公用的静态资源
components: 非路由组件(全局组件),其他组件放在views或者pages文件夹中
App.vue: 唯一的跟组件
main.js: 程序入口文件,最先执行的文件
babel.config.js: 配置文件(babel相关)
package.json: 项目的详细信息记录
package-lock.json: 缓存性文件(各种包的来源)
2.1 项目运行,浏览器自动打开
package.json
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
2.2 关闭eslint校验工具(不关闭会有各种规范,不按照规范就会报错)
根目录下创建vue.config.js,进行配置
module.exports = {
//关闭eslint
lintOnSave: false
}
2.3 src文件夹配置别名,创建jsconfig.json,用@/代替src/,exclude表示不可以使用该别名的文件
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"exclude": [
"node_modules",
"dist"
]
}
组件页面的样式使用的是less样式,浏览器不识别该样式,需要下载相关依赖
npm install --save less less-loader@5
如果想让组件识别less样式,则在组件中设置
<script scoped lang="less">
vue是单页面开发,我们只需要修改public下的index.html文件
<link rel="stylesheet" href="reset.css">
创建pages文件夹,并创建路由组件
5.1创建router文件夹,并创建index.js进行路由配置,最终在main.js中引入注册
5.2 总结
路由组件和非路由组件区别:
5.3 路由跳转方式
7.1、query、params
query、params两个属性可以传递参数
query参数:不属于路径当中的一部分,类似于get请求,地址栏表现为 /searchk1=v1&k2=v2
query参数对应的路由信息 path: "/search"
params参数:属于路径当中的一部分,需要注意,在配置路由的时候,需要占位 ,地址栏表现为 /search/v1/v2
params参数对应的路由信息要修改为path: "/search/:keyword"
这里的/:keyword就是一个params参数的占位符
params传参问题
(1)、如何指定params参数可传可不传
如果路由path要求传递params参数,但是没有传递,会发现地址栏URL有问题,详情如下:
Search路由项的path已经指定要传一个keyword的params参数,如下所示:
path: “/search/:keyword”,
执行下面进行路由跳转的代码:
this.$router.push({name:“Search”,query:{keyword:this.keyword}})
当前跳转代码没有传递params参数
地址栏信息:http://localhost:8080/#/?keyword=asd
此时的地址信息少了/search
正常的地址栏信息: http://localhost:8080/#/search?keyword=asd
解决方法:可以通过改变path来指定params参数可传可不传
path: “/search/:keyword?”,?表示该参数可传可不传
参考连接:https://blog.csdn.net/weixin_44867717/article/details/109773945
(2)、由(1)可知params可传可不传,但是如果传递的时空串,如何解决 。
this.$router.push({name:"Search",query:{keyword:this.keyword},params:{keyword:''}})
出现的问题和1中的问题相同,地址信息少了/search
解决方法: 加入||undefined,当我们传递的参数为空串时地址栏url也可以保持正常
this.$router.push({name:"Search",query:{keyword:this.keyword},params:{keyword:''||undefined}})
(3)路由组件能不能传递props数据?
可以,但是只能传递params参数,具体知识为props属性 。
7.2、传参方法
http://localhost:8080/#/search/asd?keyword=asd
多次执行相同的push问题,控制台会出现警告
例如:使用this.$router.push({name:‘Search’,params:{keyword:"…"||undefined}})时,如果多次执行相同的push,控制台会出现警告。
let result = this.$router.push({name:"Search",query:{keyword:this.keyword}})
console.log(result)
执行一次上面代码:
多次执行出现警告:
原因:push是一个promise,promise需要传递成功和失败两个参数,我们的push中没有传递。
方法:this.$router.push({name:‘Search’,params:{keyword:"…"||undefined}},()=>{},()=>{})后面两项分别代表执行成功和失败的回调函数。
这种写法治标不治本,将来在别的组件中push|replace,编程式导航还是会有类似错误
push是VueRouter.prototype的一个方法,在router中的index重写该方法即可(看不懂也没关系,这是前端面试题)
//1、先把VueRouter原型对象的push,保存一份
let originPush = VueRouter.prototype.push;
//2、重写push|replace
//第一个参数:告诉原来的push,跳转的目标位置和传递了哪些参数
VueRouter.prototype.push = function (location,resolve,reject){
if(resolve && reject){
originPush.call(this,location,resolve,reject)
}else{
originPush.call(this,location,() => {},() => {})
}
}
我们的三级联动组件是全局组件,全局的配置都需要在main.js中配置
//将三级联动组件注册为全局组件
import TypeNav from '@/pages/Home/TypeNav';
//第一个参数:全局组件名字,第二个参数:全局组件
Vue.component(TypeNav.name,TypeNav);
在Home组件中使用该全局组件
<template>
<div>
<!-- 三级联动全局组件已经注册为全局组件,因此不需要引入-->
<TypeNav/>
</div>
</template>
全局组件可以在任一页面中直接使用,不需要导入声明
下面全部商品分类就是三级联动组件
根目录下vue.config.js文件设置
module.exports = {
//关闭eslint
lintOnSave: false,
devServer: {
// true 则热更新,false 则手动刷新,默认值为 true
inline: true,
// development server port 8000
port: 8001,
}
}
注意:修改完该配置文件后,要重启一下项目
home文件夹index.vue
<template> <div> <!-- 三级联动全局组件已经注册为全局组件,因此不需要引入--> <TypeNav/> <!-- 轮播图列表--> <ListContainer/> <!-- 今日推荐--> <Recommend/> <!-- 商品排行--> <Rank/> <!-- 猜你喜欢--> <Like/> <!-- 楼层 --> <Floor/> <Floor/> <!-- 商标--> <Brand/> </div> </template> <script> import ListContainer from './ListContainer' import Recommend from './Recommend' import Rank from './Rank' import Like from './Like' import Floor from './Floor' import Brand from './Brand' export default { name: "index", components: { ListContainer, Recommend, Rank, Like, Floor, Brand, } } </script> <style scoped> </style>
axios中文文档,包含详细信息。
https://www.kancloud.cn/yunye/axios/234845
在根目录下创建api文件夹,创建request.js文件。
内容如下,当前文件代码还比较少,后续有需求可以增添内容。
import axios from "axios"; //1、对axios二次封装 const requests = axios.create({ //基础路径,requests发出的请求在端口号后面会跟改baseURl baseURL:'/api', timeout: 5000, }) //2、配置请求拦截器 requests.interceptors.request.use(config => { //config内主要是对请求头Header配置 //比如添加token return config; }) //3、配置相应拦截器 requests.interceptors.response.use((res) => { //成功的回调函数 return res.data; },(error) => { //失败的回调函数 console.log("响应失败"+error) return Promise.reject(new Error('fail')) }) //4、对外暴露 export default requests;
在根目录下的vue.config.js中配置,proxy为通过代理解决跨域问题。
我们在封装axios的时候已经设置了baseURL为api,所以所有的请求都会携带/api,这里我们就将/api进行了转换。如果你的项目没有封装axios,或者没有配置baseURL,建议进行配置。要保证baseURL和这里的代理映射相同,此处都为’/api’。
module.exports = { //关闭eslint lintOnSave: false, devServer: { // true 则热更新,false 则手动刷新,默认值为 true inline: false, // development server port 8000 port: 8001, //代理服务器解决跨域 proxy: { //会把请求路径中的/api换为后面的代理服务器 '/api': { //提供数据的服务器地址 target: 'http://39.98.123.211', } }, } }
webpack官网相关知识解读
网站中的webpack.config.js就是vue.config.js文件。
在文件夹api中创建index.js文件,用于封装所有请求
将每个请求封装为一个函数,并暴露出去,组件只需要调用相应函数即可,这样当我们的接口比较多时,如果需要修改只需要修改该文件即可。
如下所示:
//当前模块,API进行统一管理,即对请求接口统一管理
import requests from "@/api/request";
//首页三级分类接口
export const reqCateGoryList = () => {
return requests({
url: '/product/getBaseCategoryList',
method: 'GET'
})
}
当组件想要使用相关请求时,只需要导入相关函数即可,以上图的reqCateGoryList 为例:
import {reqCateGoryList} from './api'
//发起请求
reqCateGoryList();
打开一个页面时,往往会伴随一些请求,并且会在页面上方出现进度条。它的原理时,在我们发起请求的时候开启进度条,在请求成功后关闭进度条,所以只需要在request.js中进行配置。
如下图所示,我们页面加载时发起了一个请求,此时页面上方出现蓝色进度条
对应的request.js设置
import axios from "axios"; //引入进度条 import nprogress from 'nprogress'; //引入进度条样式 import "nprogress/nprogress.css"; //1、对axios二次封装 const requests = axios.create({ //基础路径,requests发出的请求在端口号后面会跟改baseURl baseURL:'/api', timeout: 5000, }) //2、配置请求拦截器 requests.interceptors.request.use(config => { //config内主要是对请求头Header配置 //比如添加token //开启进度条 nprogress.start(); return config; }) //3、配置相应拦截器 requests.interceptors.response.use((res) => { //成功的回调函数 //响应成功,关闭进度条 nprogress.done() return res.data; },(error) => { //失败的回调函数 console.log("响应失败"+error) return Promise.reject(new Error('fail')) }) //4、对外暴露 export default requests;
可以通过修改nprogress.css文件的background来修改进度条颜色。
首先确保安装了vuex,根目录创建store文件夹,文件夹下创建index.js,内容如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//对外暴露store的一个实例
export default new Vuex.Store({
state:{},
mutations:{},
actions:{},
})
如果想要使用vuex,还要再main.js中引入
main.js:
(1) 引入文件
(2) 注册store
但凡是在main.js中的Vue实例中注册的实体,在所有的组件中都会有(this.$.实体名)属性
import store from './store'
new Vue({
render: h => h(App),
//注册路由,此时组件中都会拥有$router $route属性
router,
//注册store,此时组件中都会拥有$store
store
}).$mount('#app')
如果我们没有封装请求api,而是直接调用axios,就不需要使用async await。
案例:我们将一个axios请求封装为了函数,我们在下面代码中调用了该函数:
import {reqCateGoryList} from '@/api'
export default {
actions:{
categoryList(){
let result = reqCateGoryList()
console.log(result)
}
}
}
浏览器结果
返回了一个promise,证明这是一个promise请求,但是我们想要的是图片中的data数据。
没有将函数封装前我们都会通过then()回调函数拿到服务器返回的数据,现在我们将其封装了,依然可以使用then获取数据,代码如下
actions:{
categoryList(){
let result = reqCateGoryList().then(
res=>{
console.log("res")
console.log(res)
return res
}
)
console.log("result")
console.log(result)
}
}
结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。