第一天
1)要求
1:node + webpack + VScode + 谷歌浏览器 + git
2:数组的方法 + promise + await + async + 模块化…
2)脚手架使用
vue init webpack 项目的名字
vue create 项目名称
脚手架目录:public + assets文件夹区别
node_modules:放置项目依赖的地方
public:一般放置一些共用的静态资源,打包上线的时候,public文件夹里面资源原封不动打包到dist文件夹里面
src:程序员源代码文件夹
-----assets文件夹:经常放置一些静态资源(图片),assets文件夹里面资源webpack会进行打包为一个模块(js文件夹里面)
-----components文件夹:一般放置非路由组件(或者项目共用的组件)
App.vue 唯一的根组件
main.js 入口文件【程序最先执行的文件】
babel.config.js:babel配置文件
package.json:看到项目描述、项目依赖、项目运行指令
package-lock.json:缓存性文件
README.md:项目说明文件
3)脚手架下载下来的项目稍微配置一下
1:浏览器自动打开
在package.json文件中
//脚手架五有bug,建议不配置
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
2关闭eslint校验工具
创建vue.config.js文件:需要对外暴露
module.exports = {
lintOnSave:false,
}
现在脚手架生成该文件,直接添加配置
const {
defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false
})
3 src文件夹的别名的设置
因为项目大的时候src(源代码文件夹):里面目录会很多,找文件不方便,设置src文件夹的别名的好处,找文件会方便一些
创建jsconfig.json文件,脚手架已经生成改文件
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"exclude": [
"node_modules",
"dist"
]
}
4)路由的配置
vue-router
路由分为Key-Value
前端路由:
K即为URL(网络资源定位符)
V即为相应的路由组件
1路由的一个分析
- 确定项目结构顺序:上中下 -----只有中间部分的V在发生变化,中间部分应该使用的是路由组件
- 2个非路由组件|四个路由组件
- 两个非路由组件:Header 、Footer
- 路由组件:Home、Search(有底部的Footer组件,带有二维码的);
- Login、Register(没有底部的Footer组件,带二维码的)
2安装路由
npm i vue-router@3
vue2中使用vue-router的3版本
vue3中使用vue-router的4版本
3创建路由组件【一般放在views|pages文件夹】
4配置路由,配置完四个路由组件
router/index.js
//引入VueRouter
import Vue from 'vue';
import VueRouter from 'vue-router';
//使用插件
Vue.use(VueRouter);
//引入路由 组件
import Home from '@/pages/Home'
import Search from '@/pages/Search'
import Register from '@/pages/Register'
import Login from '@/pages/Login'
//创建router实例对象,去管理一组一组的路由规则
export default new VueRouter({
routes: [{
path: '/search',
component: Search
},
{
path: '/home',
component: Home
},
{
path: '/login',
component: Login
},
{
path: '/register',
component: Register
},
]
})
main.js 添加程序
import router from '@/router';
new Vue({
render: h => h(App),
router
}).$mount('#app')
5)创建非路由组件
(2个:Header、Footer)
非路由组件使用分为几步:
第一步:定义
第二步:引入
第三步:注册
第四步:使用
项目采用的less样式,浏览器不识别less语法,需要一些loader进行处理,把less语法转换为CSS语法
1:安装less less-loader@5
npm i less less-loader@5
切记less-loader安装5版本的,不要安装在最新版本,安装最新版本less-loader会报错,报的错误setOption函数未定义
2022/3/23 可以安装最新版less-loader
"less": "^4.1.2",
"less-loader": "^10.2.0",
2:需要在style标签的身上加上lang="less"
,不添加样式不生效
6)路由的跳转
路由的跳转就两种形式:
- 声明式导航(router-link:务必要有to属性)
- 编程式导航push||replace
- 编程式导航更好用:因为可以书写自己的业务逻辑
给主页的a和搜索按钮分别换成声明式导航和编程式导航
<router-link to="/login">登录</router-link>
<router-link to="/register" class="register">免费注册</router-link>
<router-link class="logo" title="尚品汇" to="/home">
<button
class="sui-btn btn-xlarge btn-danger"
type="button"
@click="goSearch"
>
methods: {
goSearch() {
this.$router.push("./search");
},
},
7)底部组件的显示和隐藏
- 路由组件:Home、Search(有底部的Footer组件,带有二维码的);
- Login、Register(没有底部的Footer组件,带二维码的)
面试题:v-show与v-if区别?
v-show:通过样式display控制
v-if:会操作dom
面试题:开发项目的时候,优化手段有哪些?
1:v-show|v-if
2:按需加载
路由元信息meta
- 通过meta,设置一个属性,来控制是否显示底部组件
8)路由传参
- params参数:路由需要占位,属于URL当中一部分
- query参数:路由不需要占位,写法类似于ajax当中query参数
{
path: '/search/:keyword',
component: Search,
meta: {
footerShow: true
}
},
//传递字符串 ,也可以使用模板字符串
this.$router.push(
"/search/" + this.keyword + "?k=" + this.keyword.toUpperCase()
);
路由传递参数先关面试题
-
路由传递参数(对象写法)path是否可以结合params参数一起使用?
答:路由跳转传参,对象可以说name、path形式,但是path形式不可以和params结合使用 -
如何指定params参数可传可不传?
答:配置路由占位,必须传递参数,配置占位后面加上问号,那么这个参数可传可以不传
{ path: '/search/:keyword?', component: Search, meta: { footerShow: true } },
-
params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
undefined解决:params:{keyword:''|undefined}
如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
-
路由组件能不能传递props数据?
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
// props:{a:900}
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
// props:true
//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}
第二天
1)一个导航问题
编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误?
注意:编程式导航(push|replace)才会有这种情况的异常,声明式导航是没有这种问题,因为声明式导航内部已经解决这种问题。
这种异常,对于程序没有任何影响的。
-
为什么会出现这种现象:
由于vue-router最新版本,引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,- 第一种解决方案:是给push函数,传入相应的成功的回调与失败的回调
this.$router.push( { name: "search", params: { keyword: this.keyword }, query: { k: this.keyword.toUpperCase() }, }, () => { }, () => { } ); //这种解决方案可以暂时解决当前问题,但是以后再用push|replace还是会出现类似现象,因此我们需要从‘根’治病;
- 第二种,重写push方法
//this.$router.push //this :当前组件实例 //this.$router属性:VueRouter的一个实例,当在入口文件注册路由的时候,给组件实例添加$router|$route属性 //push在实例$router的原型对象上 let originPush = VueRouter.prototype.push; let originReplace = VueRouter.prototype.replace; //重写VueRouter.prototype身上的push方法了 VueRouter.prototype.push = function(location, resolve, reject) { //第一个形参:路由跳转的配置对象(query|params) //第二个参数:undefined|箭头函数(成功的回调) //第三个参数:undefined|箭头函数(失败的回调) if (resolve && reject) { //push方法传递第二个参数|第三个参数(箭头函数) //originPush:利用call修改上下文,变为(路由组件.$router)这个对象,第二参数:配置对象、第三、第四个参数:成功和失败回调函数 originPush.call(this, location, resolve, reject); } else { //push方法没有产地第二个参数|第三个参数 originPush.call( this, location, () => { }, () => { } ); } }; //重写VueRouter.prototype身上的replace方法了 VueRouter.prototype.replace = function(location, resolve, reject) { if (resolve && reject) { originReplace.call(this, location, resolve, reject); } else { originReplace.call( this, location, () => { }, () => { } ); } };
2)将Home组件的静态组件拆分
开发步骤
1.完成静态页面(样式)
2.拆分静态组件
3.发请求获取服务器数据进行展示
4.开发动态业务
拆分组件:结构+样式+图片资源
3)测试接口
这里使用postman
- 三级分类的请求地址 http://39.98.123.211/api/product/getBaseCategoryList
- 如果服务器返回code字段200,代表服务器返回数据成功
- 整个项目,接口前缀都有/api字样