前端Vue核心
开发一个前端模块可以概括为以下几个步骤:
(1)写静态页面、拆分为静态组件;
(2)发请求(API);
(3)vuex(actions、mutations、state三连操作);
(4)组件获取仓库数据,动态展示;
1、vue文件目录分析
node_modules文件夹 项目依赖 比如babel:es6语法翻译为es5兼容性更好 以及vue框架等
public文件夹:静态资源 ,webpack进行打包的时候会原封不动打包到dist文件夹中。
pubilc/index.html:是一个模板文件,作用是生成项目的入口文件,webpack打包的js,css也会自动注入到该页面中。我们浏览器访问项目的时候就会默认打开生成好的index.html。
src文件夹(程序员代码文件夹)
babel.config.js: 配置文件(babel相关)
package.json: 项目的详细信息记录 项目中有哪些依赖 项目怎么运行
package-lock.json: 缓存性文件(各种包的来源)
2、项目配置
2.1 项目运行,浏览器自动打开
找到package.json 文件 加上 --open
"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"
]
}
3、项目路由的分析(整体划分组件)
两个非路由组件定义在components当中 Headeer组件和Footer组件
- 找静态组件将样式等复制出来(由此可见less和scss等的代码健壮性)
- 安装less等插件
4、配置组件页面样式(less 第一个问题)
组件页面的样式使用的是less样式,浏览器不识别该样式,需要下载相关依赖
npm install --save less less-loader@5
如果想让组件识别less样式,则在组件中设置
<script scoped lang="less">
5、清除vue页面默认的样式
vue是单页面开发,我们只需要修改public下的index.html文件
<link rel="stylesheet" href="<%= BASE_URL %>reset.css">
@import "./iconfont.css";
/* 清除内外边距 */
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote,
dl, dt, dd, ul, ol, li,
pre,
fieldset, lengend, button, input, textarea,
th, td {
margin: 0;
padding: 0;
}
/* 设置默认字体 */
body,
button, input, select, textarea { /* for ie */
/*font: 12px/1 Tahoma, Helvetica, Arial, "宋体", sans-serif;*/
font: 12px/1.3 "Microsoft YaHei",Tahoma, Helvetica, Arial, "\5b8b\4f53", sans-serif; /* 用 ascii 字符表示,使得在任何编码下都无问题 */
color: #333;
}
h1 { font-size: 18px; /* 18px / 12px = 1.5 */ }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
h4, h5, h6 { font-size: 100%; }
address, cite, dfn, em, var, i{ font-style: normal; } /* 将斜体扶正 */
b, strong{ font-weight: normal; } /* 将粗体扶细 */
code, kbd, pre, samp, tt { font-family: "Courier New", Courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
/* 重置列表元素 */
ul, ol { list-style: none; }
/* 重置文本格式元素 */
a { text-decoration: none; color: #666;}
/* 重置表单元素 */
legend { color: #000; } /* for ie6 */
fieldset, img { border: none; }
button, input, select, textarea {
font-size: 100%; /* 使得表单元素在 ie 下能继承字体大小 */
}
/* 重置表格元素 */
table {
border-collapse: collapse;
border-spacing: 0;
}
/* 重置 hr */
hr {
border: none;
height: 1px;
}
.clearFix::after{
content:"";
display: block;
clear:both;
}
/* 让非ie浏览器默认也显示垂直滚动条,防止因滚动条引起的闪烁 */
html { overflow-y: scroll; }
a:link:hover{
color : rgb(79, 76, 212) !important;
text-decoration: underline;
}
/* 清除浮动 */
.clearfix::after {
display: block;
height: 0;
content: "";
clear: both;
visibility: hidden;
}
5、路由组件相关配置
01.安装路由
npm install --save vue-router
可查看package.json判断组件是否完成
02.创建专用文件夹放置路由组件
创建一个pages文件夹,并创建路由组件
在上面分析的时候,路由组件应该有四个: Home、 Search、Login、 Register
- -components文件夹:经常放置的非路由组件(共用全局组件)
- -pages |views文件夹:经常放置路由组件
03.配置路由
创建router文件夹,并创建index.js进行路由配置
//引入vue-router路由插件
import VueRouter from "vue-router";
//引入Vue
import Vue from "vue";
//使用插件
Vue.use(VueRouter);
import Home from '@/pages/Home'
import Login from '@/pages/Login'
import Register from '@/pages/Register'
import Search from '@/pages/Search'
export default new VueRouter({
routes: [
{
path: "/home",
component: Home
},
{
path: "/search",
component: Search
},
{
path: "/login",
component: Login
},
{
path: "/register",
component: Register
},
]
})
在main.js中引入注册
import Vue from 'vue'
import App from './App.vue'
//01.此处
import router from '@/router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
//02.此处
router
}).$mount('#app')
04.总结
路由组件和非路由组件区别:
路由组件与非路由组件的区别?
1:路由组件一般放置在pages|views文件夹,非路由组件一般放置components文件夹中
2;路由组件一般需要在router文件夹中进行注册(使用的即为组件的名字),非路由组件在使用的时候,一般都是以标签的形式使用
3:注册完路由,不管路由路由组件、还是非路由组件身上都有$route、I $router属性
$route:一般获取路由信息【路径、query.params等等】
$router:一般进行编程式导航进行路由跳转【push/replace】
05.路由的跳转
路由的跳转有两种形式:
声明式导航router-link,可以进行路由的跳转
编程式导航push|replace,可以进行路由跳转
编程式导航:声明式导航能做的,编程式导航都能在,
但是编程式导航除了可以进行路由跳转,还可以做一些其他的业务逻辑。
6、footer组件显示与隐藏(Header fotter)
实现的基本思路
- footer在登录注册页面是不存在的,所以要隐藏,v-if 或者 v-show
- 这里使用v-show,因为v-if会频繁的操作dom元素消耗性能,v-show只是通过样式将元素显示或隐藏
实现的两种方式
-
配置路由的时候,可以给路由配置元信息meta,
<Footer v-show="$route.meta.show"></Footer>
{ path: "/register", component: Register, meta: { show: false } },
-
在路由的原信息中定义show属性,用来给v-show赋值,判断是否显示footer组件
<Footer v-show="$route.path=='/home'||$route.path=='/search'"></Footer>
7、路由传参(Header fotter)
01.路由跳转有几种方式?
比如:A->B
声明式导航:router-link(务必要有to属性),可以实现路由的跳转
编程式导航:利用的是组件实例的$router.push/replace方法,可以实现路由的跳转。[(可以书写一些自己业务)
02.路由传参的两种方式params query
01.字符串传参
研究实例
按钮点击将参数传入下个页面
params传参实现方法
query传参
数据展示
02.模板字符串
就是个ES6写法
this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`)
03.对象写法
push后面装载的需要是一个参数
04.面试题
面试题1:
1.路由传递参数(对象写法)path是否可以结合params参数一起使用?
面试提2
2.如何指定params参数可传可不传?
面试提3
params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
面试提4
路由组件能不能传递props数据?
8、多次执行相同的push问题(Header fotter)
多次执行相同的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,编程式导航还是会有类似错误
如何解决
首先需要明白 在当前创建的组件当中
this:当前组件实例(search)
this.
r
o
u
t
e
r
属
性
:
当
前
的
这
个
属
性
,
属
性
值
V
u
e
R
o
u
t
e
r
类
的
一
个
实
例
,
当
在
入
口
文
件
注
册
路
由
的
时
候
,
给
组
件
实
例
添
加
router属性:当前的这个属性,属性值VueRouter类的一个实例,当在入口文件注册路由的时候,给组件实例添加
router属性:当前的这个属性,属性值VueRouter类的一个实例,当在入口文件注册路由的时候,给组件实例添加router| $route属性
push是VueRouter.prototype的一个方法,在router中的index文件中重写该方法即可(看不懂也没关系,这是前端面试题)
https://www.bilibili.com/video/BV1Vf4y1T7bw?p=10&spm_id_from=pageDriver 不理解可以看下视频 第10节 第15分钟
本质上虽说是重写 实际上还是调用了原来的方法 只是加工了一下
此代码复制到router文件夹下即可
//1、先把VueRouter原型对象的push,保存一份
let originPush = VueRouter.prototype.push;//push方法
let originReplace= VueRouter.prototype.replace//方法
//2、重写push|replace
//第一个参数:告诉原来的push,跳转的目标位置和传递了哪些参数
//第二个参数:成功回调
//第三个参数:失败的回调
VueRouter.prototype.push = function (location,resolve,reject){
//如果传递了成功和失败的回调函数 则不做处理
if(resolve && reject){
call| |apply区别
//相同点,都可以调用函数一次,都可以篡改函数的上下文一次
//不同点: call与apply传递参数: call传递参数用逗号隔开,apply方法执行,传递数组
originPush.call(this,location,resolve,reject)
}else{//否则自己添加两个函数
originPush.call(this,location,() => {},() => {})
}
}
VueRouter.prototype.replace = function (location,resolve,reject){
if(resolve && reject){
call| |apply区别
//相同点,都可以调用函数一次,都可以篡改函数的上下文一次
//不同点: call与apply传递参数: call传递参数用逗号隔开,apply方法执行,传递数组
originReplace.call(this,location,resolve,reject)
}else{
originReplace.call(this,location,() => {},() => {})
}
}
9.Home组件拆分(home)
10、Home三级联动全局组件完成(home)
01.创建基本组件
创建组件和编写基本html和css
02.组件全局注册
注意 注册全局组件需要在main.ja文件中操作
03.组件的使用
在Home组件中使用该全局组件
全局组件可以在任一页面中直接使用,不需要导入声明
11、封装ListContainer组件
01.封装样式和css
注意改变图片的路径
12、封装TodayRecommend组件
01.封装样式和css
注意改变图片的路径
13、封装Rank组件
01.封装样式和css
注意改变图片的路径
14、封装Like组件
01.封装样式和css
注意改变图片的路径
15、封装Floor组件
01.封装样式和css
注意改变图片的路径
16、封装Brand组件
01.封装样式和css
注意改变图片的路径
17.封装axios
01.封装request文件
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',
//代表请求超时的时间是5s
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;
02.封装api统一管理文件
在文件夹api中创建index.js文件,用于封装所有请求
将每个请求封装为一个函数,并暴露出去,组件只需要调用相应函数即可,这样当我们的接口比较多时,如果需要修改只需要修改该文件即可。
如下所示:
//当前模块,API进行统一管理,即对请求接口统一管理
import requests from "@/api/request";
//首页三级分类接口 /api/product/getBaseCategoryList get请求 无参数
export const reqCateGoryList = () => {
return requests({
url: '/product/getBaseCategoryList',
method: 'GET'
})
}
当组件想要使用相关请求时,只需要导入相关函数即可,以上图的reqCateGoryList 为例:
import {reqCateGoryList} from './api'
//发起请求
reqCateGoryList();
03.解决跨域问题
在根目录下的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',
//因为都有api 所以不再路径重写
//pathRewrite:{'^/api':''}
}
},
}
}