Vue项目笔记
Vue项目笔记
lycheeKing前端Vue核心
开发一个前端模块可以概括为以下几个步骤:
(1)写静态页面、拆分为静态组件;
(2)发请求(API);
(3)vuex(actions、mutations、state三连操作);
(4)组件获取仓库数据,动态展示
1、vue文件目录分析
public文件夹:静态资源,webpack进行打包的时候会原封不动打包到dist文件夹中。
pubilc/index.html是一个模板文件,作用是生成项目的入口文件,webpack打包的js,css也会自动注入到该页面中。我们浏览器访问项目的时候就会默认打开生成好的index.html。
src文件夹(程序员代码文件夹)
1 | assets: 存放公用的静态资源 |
babel.config.js: 配置文件(babel相关)
package.json: 项目的详细信息记录
package-lock.json: 缓存性文件(各种包的来源)
2、项目配置
2.1 项目运行,浏览器自动打开
1 | package.json |
2.2 关闭eslint校验工具(不关闭会有各种规范,不按照规范就会报错)
- 根目录下创建vue.config.js,进行配置
1 | module.exports = { |
2.3 src文件夹配置别名,创建jsconfig.json,用@/代替src/,exclude表示不可以使用该别名的文件
1 | { |
3、组件页面样式
组件页面的样式使用的是less样式,浏览器不识别该样式,需要下载相关依赖
npm install --save less less-loader@5
如果想让组件识别less样式,则在组件中设置<script scoped lang="less">
4、清除vue页面默认的样式
vue是单页面开发,我们只需要修改public下的index.html文件
1 | <link rel="stylesheet" href="reset.css"> |
5、pages文件夹
创建pages文件夹,并创建路由组件
5.1创建router文件夹,并创建index.js进行路由配置,最终在main.js中引入注册
5.2 总结
路由组件和非路由组件区别:
- 非路由组件放在components中,路由组件放在pages或views中
- 非路由组件通过标签使用,路由组件通过路由使用
- 在main.js注册玩路由,所有的路由和非路由组件身上都会拥有$router $route属性
- $router:一般进行编程式导航进行路由跳转
- $route: 一般获取路由信息(name path params等)
5.3 路由跳转方式
- 声明式导航router-link标签 ,可以把router-link理解为一个a标签,它 也可以加class修饰
- 编程式导航 :声明式导航能做的编程式都能做,而且还可以处理一些业务
6、footer组件显示与隐藏
- footer在登录注册页面是不存在的,所以要隐藏,v-if 或者 v-show
- 这里使用v-show,因为v-if会频繁的操作dom元素消耗性能,v-show只是通过样式将元素显示或隐藏
- 配置路由的时候,可以给路由配置元信息meta,
- 在路由的原信息中定义show属性,用来给v-show赋值,判断是否显示footer组件
7、路由传参
7.1、query、params
query、params两个属性可以传递参数
query参数:不属于路径当中的一部分,类似于get请求,地址栏表现为
/search?k1=v1&k2=v2
query参数对应的路由信息path: "/search"
params参数:属于路径当中的一部分,需要注意,在配置路由的时候,需要占位 ,地址栏表现为/search/v1/v2
params参数对应的路由信息要修改为**path: "/search/:keyword"
** 这里的/:keyword就是一个params参数的占位符params传参问题
(1)、如何指定params参数可传可不传1
2
3
4
5
6
7
8
9
10
11如果路由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?",?表示该参数可传可不传(2)、由(1)可知params可传可不传,但是如果传递的时空串,如何解决 。
1
2
3
4this.$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、传参方法
- 字符串形式
this.$router.push("/search/"+this.params传参+"?k="+this.query传参)
- 模板字符串
this.router.push("/search/+router.push("/search/+router.push("/search/+{this.params传参}?k=${this.query传参}")
注意: 上面字符串的传参方法可以看出params参数和 ’/‘ 结合,query参数和 ?结合
http://localhost:8080/#/search/asd?keyword=asd
上面url中asd为params的值,keyword=asd为query传递的值。
- 对象(常用)
this.$router.push({name:“路由名字”,params:{传参},query:{传参})。
以对象方式传参时,如果我们传参中使用了params,只能使用name,不能使用path,如果只是使用query传参,可以使用path 。
8、多次执行相同的push问题
多次执行相同的push问题,控制台会出现警告
例如:使用this.$router.push({name:‘Search’,params:{keyword:”…”||undefined}})时,如果多次执行相同的push,控制台会出现警告。
1 | let result = this.$router.push({name:"Search",query:{keyword:this.keyword}}) |
执行一次上面代码:
多次执行出现警告:
原因:push是一个promise,promise需要传递成功和失败两个参数,我们的push中没有传递。
方法:
1 | this.$router.push({name:‘Search’,params:{keyword:"…"||undefined}},()=>{},()=>{}) |
后面两项分别代表执行成功和失败的回调函数。
这种写法治标不治本,将来在别的组件中push|replace,编程式导航还是会有类似错误
push是VueRouter.prototype的一个方法,在router中的index重写该方法即可(看不懂也没关系,这是前端面试题)
1 | //1、先把VueRouter原型对象的push,保存一份 |
9、定义全局组件
我们的三级联动组件是全局组件,全局的配置都需要在 main.js 中配置
详细配置信息:
1 | import Vue from 'vue' |
在Home组件中使用该全局组件
1 | <template> |
全局组件可以在任一页面中直接使用,不需要导入声明
下面全部商品分类就是三级联动组件
10、代码改变时实现页面自动刷新
根目录下 vue.config.js
文件设置
1 | module.exports = { |
注意:修改完该配置文件后,要重启一下项目——–>此项感觉一般默认就好,不需要改动
11、Home首页其它组件
home文件夹index.vue
1 | <template> |
postman测试接口
- postman工具测试,接口是没有问题的
- 如果服务器返回的数据code字段是200,代表服务器返回数据成功
- 整个项目,接口前缀都有/api
12、封装axios
1.为什么需要进行二次封装axios?
为了用到拦截器:
请求拦截器:在发送请求之前可以处理业务
响应拦截器:服务器数据返回以后,处理数据
附:
axios简介http://t.csdn.cn/znBCQ
axios中文文档,包含详细信息。
https://www.kancloud.cn/yunye/axios/234845
在根目录下创建api文件夹,创建request.js文件。
内容如下,当前文件代码还比较少,后续有需求可以增添内容。
request.js ==在配置对象中注意是否有拼写错误==
1 | //对于axios进行二次封装 |
13、前端通过代理解决跨域问题
在根目录下的==vue.config.js==中配置 proxy
为通过代理解决跨域问题。
我们在封装axios的时候已经设置了baseURL为api,所以所有的请求都会携带/api,这里我们就将/api进行了转换。如果你的项目没有封装axios,或者没有配置baseURL,建议进行配置。要保证baseURL和这里的代理映射相同,此处都为’/api’。
1 | module.exports = { |
webpack官网相关知识解读
网站中的webpack.config.js就是vue.config.js文件。
14、请求接口统一封装
在文件夹api中创建index.js文件,用于封装所有请求
将每个请求封装为一个函数,并暴露出去,组件只需要调用相应函数即可,这样当我们的接口比较多时,如果需要修改只需要修改该文件即可。
1 | //当前这个模块:API进行统一管理,即对请求接口统一管理 |
当组件想要使用相关请求时,只需要导入相关函数即可,以上图的reqCateGoryList 函数 为例:
1 | //引入进度条 |
15、nprogress进度条插条
打开一个页面时,往往会伴随一些请求,并且会在页面上方出现进度条。它的原理时,在我们发起请求的时候开启进度条,在请求成功后关闭进度条,所以只需要在request.js中进行配置。
如下图所示,我们页面加载时发起了一个请求,此时页面上方出现蓝色进度条
对应的request.js设置
1 | //对于axios进行二次封装 |
可以通过修改nprogress.css文件的background来修改进度条颜色。
16、手动引入Vuex
首先确保安装了vuex(==注意:==vue2的安装@Vuex3,vue3的安装@Vuex4),根目录创建store文件夹,文件夹下创建index.js,内容如下:
1 | import Vue from 'vue' |
如果想要使用vuex,还要再main.js中引入
main.js:
(1) 引入文件
(2) 注册store
但凡是在main.js中的Vue实例中注册的实体,在所有的组件中都会有(this.$.实体名)属性
1 | import store from './store' |
完成TypeNav三级联动展示数据业务
==将全局组件 (TypeNav)移到components目录下==
17、async await使用
如果我们没有封装请求api,而是直接调用axios,就不需要使用async await。
案例:我们将一个axios请求封装成了函数**reqCateGoryList
**,我们在下面代码中调用了该函数:
1 | import {reqCateGoryList} from '@/api' |
浏览器结果
控制台打印输出了一个promise,证明这是一个promise
请求,但是我们想要的是图片中的data
数据。
没有将函数封装前我们都会通过then()回调函数拿到服务器返回的数据,现在我们将其封装了,依然可以使用then获取数据,代码如下
1 | actions:{ |
结果
由于我们的promis是异步请求,我们发现请求需要花费时间,但是它是异步的,所有后面的console.log(“result”);console.log(result)会先执行,等我们的请求得到响应后,才执行console.log(“res”);console.log(res),这也符合异步的原则,但是我们如果在请求下面啊执行的是将那个请求的结果赋值给某个变量,这样就会导致被赋值的变量先执行,并且赋值为undefine,因为此时promise还没有完成。
所以我们引入了async await,async写在函数名前,await写在api函数前面。await含义是async标识的函数体内的并且在await标识代码后面的代码先等待await标识的异步请求执行完,再执行。这也使得只有reqCateGoryList执行完,result 得到返回值后,才会执行后面的输出操作。
1 | async categoryList(){ |
结果
1 | //Vuex=====>home模块的小仓库 |
完成一级分类动态添加背景颜色
第一种解决方案:采用样式完成(可以的)