您现在的位置是:首页 >学无止境 >Vue使用说明、项目的其他配置、项目路由的分析、完成非路由组件的创建【Vue项目】网站首页学无止境
Vue使用说明、项目的其他配置、项目路由的分析、完成非路由组件的创建【Vue项目】
一、Vue使用说明
-
vue-cli脚手架初始化项目。
node + webpack + 淘宝镜像 -
node_module文件夹:项目依赖文件夹
-
public文件夹:一般放置一些静态资源(图片),需要注意,放在public文件夹中的静态资源,webpack进行打包的时候,会原封不动打包到dist文件夹中。
-
src文件夹(程序员源代码文件夹):
assets文件夹
:一般也是放置静态资源(一般防止多个组件共用的静态资源),需要注意,放置在assets文件夹里面的静态资源,在webpack打包的时候,webpack会把静态资源当作一个模块打包到JS文件里面。components文件夹
:一般放置的是非路由组件(全局组件)App.vue
:唯一的根组件,vue当中的组件(.vue)main.js
:程序入口文件,也是整个程序当中最先执行的文件 -
babel.config.js:配置文件(babel文件)
-
package.json文件:认为项目‘身份证’,记录项目叫做什么、项目怎样运行、项目当中有哪些依赖。
-
package-lock.json:缓存性文件
二、项目的其他配置
- 项目运行起来的时候,让浏览器自动打开
– package.json
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
- eslint校验功能关闭
– 在根目录下创建一个vue.config.js文件
比如:声明变量但是没有使用eslint校验工具报错
module.exports = {
//关闭eslint
lintOnSave: false
}
- src文件夹简写方法,配置别名。
– 在根目录下创建一个jsconfig.json文件夹,配置别名@提示【@代表的是src文件夹,这样将来文件过多,找的时候方便很多】
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
三、项目路由的分析
vue-router
前端所谓路由:KV键值对
key:URL(地址栏中的路径)
value:相应的路由组件
注意:项目是上中下结构
路由组件:Home首页路由组件、Search路由组件、login登录路由、Register注册路由
非路由组件:Header【首页、搜索页】、Footer【在首页、搜索页】但是在登录|注册页面没有
四、完成非路由组件的创建
在项目当中,不再以HTML + CSS 为主,主要搞业务、逻辑
在开发项目的时候:
- 书写静态页面(HTML+ CSS)
- 拆分组件
- 获取服务器的数据动态展示
- 完成相应的动态的业务逻辑
注意1:创建组件的时候,组件结构 + 组件的样式 + 图片资源
注意2:项目采用的是less样式,浏览器不识别less样式,需要通过npm i less less-loader@6 --save-dev
【安装六版本的】进行处理less,把less样式变为css样式,浏览器才可以识别。
注意3:如果想让组件识别less
样式,需要在style标签的身上加上lang=less
4.1 使用组件的步骤(非路由组件)
- 创建或者定义
- 引入
- 注册
- 使用
- 路由组件的搭建
vue-router
在上面分析的时候,路由组件应该有四个:Home、Search、Login、Register
– components文件夹:经常放置的非路由组件(共用的全局组件)
– pages|views文件夹:经常放置路由组件
5.1 配置路由
项目当中配置的路由一般放置在router文件夹中
5.2 总结
路由组件与非路由组件的区别?
- 路由组件一般放置在
pages
|views
文件夹,非路由组件一般放置components
文件夹中 - 路由组件一般需要在router文件夹中进行注册(使用的即为组件的名字),非路由组件在使用的时候,一般都是以标签的形式使用
- $ route:一般获取路由信息【路径、query、params等等】;$ router:一般进行编程式导航进行路由跳转【
push
|replace
】 - 注册完路由,不管是路由组件还是非路由组件身上都有
$ route
|$ router
属性
5.3 路由的跳转?
路由的跳转有两种形式:
- 声明式导航`router-link`,可以进行路由的跳转
- 编程式导航`push`|`replace`,可以进行路由跳转
编程式导航:声明式导航能做的,编程式导航都能做,但是编程式导航除了可以进行路由调和在哪,还可以做一些其他的业务逻辑。
- Footer组件的显示与隐藏
显示或者隐藏组件:v-if
|v-show
Footer组件:在Home、Search显示Footer组件
Footer组件:在登录、注册时候隐藏的
6.1 我们可以根据组件身上的$route获取当前路由的信息,通过路由路径判断Footer显示与隐藏。
6.2 配置路由的时候,可以给路由添加路由元信息【meta】,路由需要配置对象,它的key不能瞎写、胡写、乱写。
- 路由传参
7.1 路由的跳转有几种方式?
比如:A->B
声明式导航:router-link(务必要有to属性),可以实现路由的跳转
编程式导航:利用的是组件实例的$router.push | replace方法,可以实现路由的跳转。(可以书写一些自己的业务)
7.2 路由传参,参数有几种写法?
params参数:属于路径当中的一部分,需要注意,在配置路由的时候,需要占位
query参数:不属于路径当中的一部分,类似于ajax中的queryString ,不需要占位。
- 路由传参相关面试题
8.1 路由传递参数(对象写法)path是否可以结合params参数一起使用?
答:路由跳转传参的时候,对象的写法可以是name、path形式,但是需要注意的是,path的这种写法不能与params参数一起使用
8.2 如何指定params参数可传可不传?
比如:配置路由的时候,占位了(params参数),但是路由跳转的时候就不传递。路径会出现问题
如果路由要求传递params参数,但是你就不传递params参数,发现一件事情,URL会有问题的
如何指定params参数可以传递或者不传递,在配置路由的时候,在占位的后面加上一个问好【params可以传递或者不传递】
8.3 params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
使用undefined解决:params参数可以传递、不传递(空的字符串)
8.4 路由组件能不能传递props数据?
可以的:三种写法
布尔值的写法: params
props: true,
对象写法:额外的给路由组件传递一些props
props: {a: 1, b: 2}
函数写法:可以把params参数、query参数,通过props传递给路由组件
props: ($route) => ({keyWord: $route.params.keyWord, k:$route.query.k})
- 编程式路由跳转到当前路由(参数不变),多次执行会抛出
NavigationDuplicated
的警告错误?
– 路由跳转有两种形式:声明式导航、编程式导航
– 声明式导航没有这类问题,因为Vue-router底层已经处理好了
9.1 为什么编程式导航进行路由跳转的时候,就有这种警告错误?
“vue-router”: “^3.5.2”:最新的vue-router引入promise
9.2 通过给push方法传递相应的成功、失败的回调函数,可以捕获到当前错误,可以解决。
9.3 通过底部的代码,可以实现解决错误
this.$router.push({
name: 'search',
params: {keyWord: this.keyWord},
query: {k: this.keyWord.toUpperCase()},
() => {},
() => {}
})
这种写法:治标不治本,将来在别的组件当中push | replace,编程式导航还是有类似错误。
9.4
this:当前组件实例(search)
this.$router属性:当前的这个属性,属性值VueRouter类的一个实例,当在入口文件注册路由的时候,给组件实例添加的 $router | $route 属性
push:VueRouter类的一个实例
解决方法:
- 先把Vuerouter原型对象的push,先保存一份
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;
- 重写 push | replace
第一个参数:告诉原来push方法,你往哪里跳转(传递哪些参数)
第二个参数:成功回调
第三个参数:失败的回调 - call | apply区别:
相同点,都可以调用函数一次,都可以篡改函数的上下文一次
不同点:call与apply传递参数:call传递参数用个逗号隔开,apply方法执行,传递数组
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;
VueRouter.prototype.push = function(location, resolve, reject){
if(resolve && reject){
originPush.call(this, location, resolve, reject)
}else{
originPush.call(this.location, () => {}, () => {})
}
}
VueRouter.prototype.replace = function(location, resolve, reject){
if(resolve && reject){
originReplace.call(this, location, resolve, reject);
}else{
originReplace.call(this, location, ()=>{}, ()=>{})
}
}
- Home模块组件拆分
– 先把静态页面完成
– 拆分出静态组件
– 获取服务器的数据进行展示
– 动态业务 - 三级联动组件完成
– 由于三级联动,在Home、Search、Detail,把三级联动注册为全局组件。
好处:只需要注册一次,就可以在项目的任意地方使用 - 完成其余静态组件
HTML + CSS + 图片资源 —信息【结构、样式、图片资源】 - Postman测试接口
GET请求 http://gmall-h5-api.atguigu.cn/api/product/getBaseCategoryList
– 刚刚经过postman工具测试,接口是没有问题的
– 如果服务器返回的数据code字段200,代表服务器返回数据成功
– 整个项目,接口的前缀都有/api字样
- axios二次封装
XMLHttpRequest、fetch、JQ、axios
14.1 为什么需要进行二次封装axios?
请求拦截器、响应拦截器。
请求拦截器:可以在发送请求之前可以处理一些业务
相应拦截器:当服务器数据返回以后,可以处理一些事情
14.2 在项目当中经常出现API文件夹【axios】
接口当中:路径都带有/api
baseURL: '/api'
14.3 有些朋友axios基础不好,可以参考git | NPM 关于axios文档
- 接口统一管理
项目很小:完全可以在组件的生命周期函数中去发请求
项目很大:axios.get(‘xxx’)
15.1 跨域问题
什么是跨域(面试也常问以及跨域的解决问题):协议、域名、端口号不同请求,称之为跨域
http://localhost:8080/#/home -----前端项目本地服务器
http://gmall-h5-api.atguigu.cn-----后台服务器
- nprogress进度条的使用
start:进度条开始
done:进度条结束
进度条颜色可以修改的,当然需要修改人家的样式
- vuex状态管理库
17.1 vuex是什么?
vuex是官方提供一个插件,状态管理看,集中式管理项目中组件共用的数据
切记,并不是全部的项目都需要vuex,如果项目很小,完全不需要vuex;如果项目很大,组件很多,数据很多,数据维护很费劲,这时就需要Vuex
Vuex有几个核心的概念
state:仓库存储数据的地方
mutations:唯一修改state手段
actions:异步操作,通常我们可以调用接口信息
getters:可以简单理解为是计算属性computed,它们的作用是相似的,特点是相似的,用法也是相似的
modules:模块式开发
17.2 vuex的基本使用
import Vue from 'vue'
import Vuex from 'vuex'
// 需要使用插件一次
Vue.use(Vuex);
// 引入小仓库
import home from './home'
import search from './search'
// 对外暴露Store类的一个实例
export default new Vuex.Store({
// 实现Vuex仓库模块式开发存储数据
modules: {
home,
search
}
});
17.3 vuex实现模块式开发
如果项目过大,组件过多,接口也很多,数据也很多,可以让Vuex实现模块式开发
模拟state存储数据
- 完成TypeNav三级联动展示数据业务
import {mapState} from 'vuex'
export default {
name: "TypeNav",
// 组件挂载完毕:可以向服务器发请求
mounted(){
// 通知Vuex发请求,获取数据,存储于仓库当中
this.$store.dispatch('categoryList')
},
computed: {
...mapState({
// 右侧需要的是一个函数,当使用这个计算属性的时候,右侧的函数会立即执行一次
// 注入一个参数state,其实即为大仓库中的数据
categoryList: state => state.home.categoryList
})
}
};
store/home/index.js
import { reqCategoryList } from "@/api"
// home模块的小仓库
const state = {
// state中的数据默认初始值别瞎写,服务器返回的是对象,那么起始值就是一个对象;服务器返回的是数组,那么起始值就是数组
// 根据接口的返回值初始化的
categoryList: [],
}
const mutations = {
CATEGORYLIST(state, categoryList){
state.categoryList = categoryList
}
}
const actions = {
// 通过API里面的接口函数调用,向服务器发请求,获取服务器数据
async categoryList({commit}){
let result = await reqCategoryList()
if(result.code == 200){
commit("CATEGORYLIST", result.data)
}
}
}
const getters = {}
export default {
state, mutations, actions, getters
}