需要先安装node,webpack,cli脚手架
如果要卸掉旧版本脚手架(3以下):npm uninstall -g vue-cli
;淘宝镜像安装的cnpm uni vue-cli -g
(前面加c)
安装新版本npm install -g @vue/cli
淘宝镜像安装cnpm install -g @vue/cli
查看版本vue --version
或vue -V
安装:npm install -g @vue/cli
卸载:npm uninstall -g @vue/cli
指定版本安装(3):npm install -g @vue/[email protected]
等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmVxXOSD-1645519249982)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220219234100391.png)]
(4):npm install -g @vue/[email protected]
vue ui
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jVZnXTCN-1645519249983)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220219225918588.png)]
启动在http://localhost:8000/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BtWhIhXF-1645519249984)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220219230404609.png)]
(CLI 2)
vue init webpack 项目的名字
(CLI 3)在命令行中目标位置
vue create demo(项目名)
node_modules:放置项目依赖
public + assets文件夹区别:
public:一般放置静态资源,打包上线的时候,public文件夹里面资源原封不动打包到dist文件夹里面;
src:程序员源代码文件夹
-assets文件夹:经常放置一些多个组件共用的静态资源(图片),assets文件夹里面资源webpack会进行打包为一个模块(js文件夹里面)
-components文件夹:一般放置非路由组件(或者项目共用的组件)
App.vue: 唯一的根组件
main.js: 入口文件【程序最先执行的文件】
.gitignore:git忽略文件
babel.config.js:babel配置文件
package.json:记录项目描述、项目依赖、项目运行指令等项目信息
package-lock.json:缓存性文件
README.md:项目说明文件
(我习惯不改)
在package.json文件中
“scripts”: {
“serve”: “vue-cli-service serve --open”,
“build”: “vue-cli-service build”,
“lint”: “vue-cli-service lint”
},
加上–open
启动命令:
npm run serve
输入命令启动后浏览器自动打开
(可以关)
在根目录下创建vue.config.js文件:
module.exports = {
lintOnSave:false,
}
(会方便)
因为项目大的时候src(源代码文件夹):里面目录会很多,找文件不方便,设置src文件夹的别名的好处,找文件会方便一些
创建jsconfig.json文件
{
“compilerOptions”: {
“baseUrl”: “./”,
“paths”: {
“@/": [
"src/”
]
}
},
“exclude”: [
“node_modules”,
“dist”
]
}
vue-router
路由分为Key:Value键值对
node平台(并非语言)
对于后台而言:K即为URL地址 V即为相应的中间件
http://localhost:8080/0607
app.get(“/0607”,(res,req)=>{
res.send(‘我是祖国的花朵’);
});
前端路由:
K即为URL(网络资源定位符)
V即为相应的路由组件
确定项目结构顺序:上中下 -----只有中间部分的V在发生变化,中间部分应该使用的是路由组件
2个非路由组件|四个路由组件:
两个非路由组件:Header 、Footer
路由组件:Home、Search、Login(没有底部的Footer组件)、Register(没有底部的Footer组件)
(2个:Header、Footer)
1、书写静态页面;2、拆分组件;3、获取服务器的数据动态展示;4、完成相应的动态业务逻辑
非路由组件使用步骤:
定义;引入;注册;使用
非路由组件的结构的搭建:
静态页面:
结构 + 样式 + 图片资源
将写好的静态页面引入,拆分组件
方法:在components下建文件夹,将组件相关放入一个文件夹
components文件夹:通常放置非路由组件或共用的全局组件
如Header:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sx0AHHgo-1645519249984)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220183616937.png)]
如果项目采用的less样式,浏览器不识别less语法,需要一些loader进行处理,把less语法转换为CSS语法
1:安装less less-loader@5
命令:
npm install less less-loader@5 --save-dev
切记less-loader安装5版本的,不要安装在最新版本,安装最新版本less-loader会报错,报的错误setOption函数未定义
2:需要在style标签的身上加上lang=“less”(识别less)
在App.vue中引入:import+修改components
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5EV3ehUA-1645519249985)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220185859193.png)]
注册后可以在template中引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EmE5i8pD-1645519249985)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220185951932.png)]
注:一些样式如reset样式可以放在public中,在index.html中引入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zethqSI1-1645519249986)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220190213064.png)]
同理,引入多个组件App.vue:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHsBQTRG-1645519249986)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220191517511.png)]
cnpm install --save vue-router
–save:可以让你安装的依赖,在package.json文件当中进行记录
安装指定版本:
cnpm install --save vue-router@3
【一般放在views/pages文件夹】
在views/pages文件夹下建文件夹放置组件。
配置路由一般放在src的router文件夹下(新建)
新建index.js文件,配置路由
引入vue,vue-router:
import Vue from 'vue';
import VueRouter from 'vue-router'
使用插件:
Vue.use(VueRouter);
引入路由组件:
import Home from '@/views/Home/homeIndex'
import Login from '@/views/Login/loginIndex'
配置路由:
export default new VueRouter({
routes:[
{
path:"/home",
component:Home
},
{
path:"/login",
component:Login
}
]
})
重定向:开始时跳转到首页
{
path:"/",
component:Home
},
代码:
// 配置路由
import Vue from 'vue';
import VueRouter from 'vue-router'
// 使用插件
Vue.use(VueRouter);
// 引入路由组件
import Home from '@/views/Home/homeIndex'
import Login from '@/views/Login/loginIndex'
import Register from '@/views/Register/registerIndex'
import Search from '@/views/Search/searchIndex'
// 配置路由
export default new VueRouter({
routes:[
{
path:"/",
component:Home
},
{
path:"/home",
component:Home
},
{
path:"/login",
component:Login
},
{
path:"/register",
component:Register
},
{
path:"/search",
component:Search
}
]
})
之后再在main.js中配置
引入注册路由:
import Vue from 'vue'
import App from './App.vue'
// 引入路由
import router from '@/router/index'
new Vue({
render: h => h(App),
// 注册路由(kv一致且省略v)
// 这里书写router时,组件身上同时都拥有$route,$routers属性
router
}).$mount('#app')
在app.vue中设置路由出口
或
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qvphr1wc-1645519249987)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220195017353.png)]
配置完四个路由组件
路由的跳转就两种形式:声明式导航(router-link:务必要有to属性)、编程式导航push||replace
登录
点击事件
goSearch(){
this.$router.push('/search')
}
编程式导航可以传参,可以书写自己的业务逻辑
路由组件与非路由组件的区别?
1,路由组件一般放置在pages|views文件夹,非路由组件一般放置components文件夹中;
2,路由组件一般需要在router文件夹中进行注册(使用的即为组件的名字),非路由组件在使用的时候,一般都是以标签的形式使用;
3,注册完路由,不管路由路由组件、还是非路由组件身上都有$route
,$router
属性;
$route
:一般获取路由信息【路径、query、params等等】(this.$route
.path
this.$route
.params|query
this.$route
.meta)
$router
:一般进行编程式导航进行路由跳转【push|replace】(this.$router
.push|this.$router
.replace)
登录注册时隐藏Footer组件,其他显示
可以根据组件身上$router获取路由信息,通过路由路径判断
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSuRqLa3-1645519249987)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220202040948.png)]
或
定义路由时可以配置meta字段
router/index:
{
path:"/login",
component:Login,
meta:{show:false}
},
App.vue:
v-show:通过样式display控制
v-if:通过元素上树与下树进行操作
面试题:开发项目的时候,优化手段有哪些?
1:v-show|v-if
2:按需加载
两种方式:声明式,编程式
参数:
params参数:路由需要占位,属于URL当中一部分;
query参数:路由不需要占位,不属于路径当中一部分,写法类似于ajax当中query参数
会拼在URL中:
在router/index.js中占位
{
path:"/search/:key",
component:Search,
meta:{show:true}
}
页面中:
获得key:(v-model=“key”)
data添加key=‘’
data () {
return {
key:''
}
},
方法中拼上this.key
goSearch(){
this.$router.push('/search/'+this.key)
}
在输入框输入字符串后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mGMRie0L-1645519249987)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220222342178.png)]
不需要占位
goSearch(){
this.$router.push("/search/" +"?k="+ this.key.toUpperCase())
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gr3bWxw0-1645519249988)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220223552916.png)]
方法:
goSearch(){
this.$router.push("/search/" +this.key+"?k="+ this.key.toUpperCase())
}
data
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q4Uk8ASb-1645519249988)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220224245916.png)]
在search组件中设置显示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0tvFNyx-1645519249988)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220224500797.png)]
显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MLF4QZ8n-1645519249989)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220224547145.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsMQZsR0-1645519249989)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220224341182.png)]
goSearch(){
this.$router.push(`/search/${this.key}?k=${this.key.toUpperCase()}`)
}
效果同上
router/index.js中需要有name:
{
path:"/search/:key",
component:Search,
meta:{show:true},
name:"search"
}
方法:
this.$router.push({name:"search",params:{key:this.key},query:{k:this.key.toUpperCase()}})
可以成功[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88qQ7dA5-1645519249990)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220225527086.png)]
1、编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误?
注意:编程式导航(push|replace)才会有这种情况的异常,声明式导航是没有这种问题,因为声明式导航内部已经解决这种问题。
这种异常,对于程序没有任何影响的。
为什么会出现这种现象:
由于vue-router最新版本3.5.2,引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,
①第一种解决方案:是给push函数,传入相应的成功的回调与失败的回调给promise
function push(){
return new Promise((resolve,reject) => {
})
}
例子:增加成功与失败回调
this.$router.push({name:"search",params:{key:this.key},query:{k:this.key.toUpperCase()}},()=>{},(error)=>{console.log(error)})
这种解决方案可以暂时解决当前问题,但是以后再用push|replace还是会出现类似现象,因此我们需要从‘根’治病;
②push方法是VueRouter的原型对象一个实例
VueRouter.prototype.push = function(){
//原型对象的方法
}
let $router = new VueRouter();
$router = new VueRouter();
$router.push();
this.$router.push();
要解决问题:重写push|replace方法(router/index.js)
重写push方法:
第一个参数:告诉原来push方法传递哪些参数;第二个:成功回调;第三个:失败回调
//先保存原方法
let originPush = VueRouter.prototype.push;
//重写
VueRouter.prototype.push = function(location,resolve,reject){
if(resolve && reject){
//call|apply
//相同点:都可以调用函数一次,都可以篡改函数的上下文一次
//不同:传递参数时,call多个参数用逗号隔开,apply方法执行,传递数组
originPush.call(this,location,resolve,reject);
}else{
originPush.call(this,location,()=>{},()=>{});
}
}
重写replace方法
//先保存原方法
let originReplace = VueRouter.prototype.replace;
//重写
VueRouter.prototype.replace = function(location,resolve,reject){
if(resolve && reject){
//call|apply
//相同点:都可以调用函数一次,都可以篡改函数的上下文一次
//不同:传递参数时,call用逗号隔开,apply方法执行,传递数组
originReplace.call(this,location,resolve,reject);
}else{
originReplace.call(this,location,()=>{},()=>{});
}
}
路由传递参数(对象写法)path是否可以结合params参数一起使用?
this.$router.push({path:'/search',params:{key:this.key}})
不可以:不能这样书写,程序会崩掉
如何指定params参数可传可不传?
配置路由时占位后加问号:
path:"/search/:key?",
params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
使用undefined
this.$router.push({name:"search",params:{key:this.key || undefined},query:{k:this.key.toUpperCase()}})
如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
路由组件能不能传递props数据?
props通常用于父子组件通信
可以,三种写法
①布尔值写法,params
index.js设置props
props:true
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QtPgfZWq-1645519249990)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220233836282.png)]
测试可以看到可以传参
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hIPiRKE3-1645519249990)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220233734786.png)]
接收参数:(只能传递params参数)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pMI3AIgB-1645519249991)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220234311630.png)]
②对象写法
(额外给路由组件传递props参数)
props:{a:1,b:2}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H5SgZvGv-1645519249991)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220234615538.png)]
接收:props:[‘a’,‘b’]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIjKZHYb-1645519249991)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220235423636.png)]
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lp6ujVOA-1645519249992)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220235353816.png)]
③函数写法
可以params参数、query参数,通过props传递给路由组件
props:($route) => {
return {key:$route.params.key,k:$route.query.k}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2bm98fBl-1645519249992)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220220235848226.png)]
可以拿到key、k
接收参数:
index.js
props:($route) => {
return {ke:$route.params.key,k:$route.query.k}
}
页面接收:
export default
props:['ke','k']
template
params参数 -> {{$route.params.key}} - {{ke}}
query参数 -> {{$route.query.k}} - {{k}}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8b6cwdc-1645519249992)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220221000615276.png)]
改写(简写):注意加括号,不然箭头函数认为函数体不正确
props:($route) => ({ke:$route.params.key,k:$route.query.k})
5.call|apply
相同点:都可以调用函数一次,都可以篡改函数的上下文一次;
不同:传递参数时,call多个参数用逗号隔开,apply方法执行,传递数组.
组件拆分时只看静态页面,比如轮播图只显示第一个页面,将其余页面注释掉
将Home组件的静态组件拆分
1静态页面(样式)
2拆分静态组件
3发请求获取服务器数据进行展示
4开发动态业务
拆分组件:结构+样式+图片资源
一共要拆分为七个组件
结构相似可以拆成一个组件,复用
三级联动在多个页面使用,注册为全局组件。
好处:只需要注册一次,就可以在项目任意地方使用
(如果文件夹中vue文件命名为index.vue,可以少写一层路径)
main.js:
// 引入三级联动组件--全局组件
import TypeNav from '@/views/Home/TypeNav/TypeNav'
//第一个参数:全局组件的名字,第二个参数:哪一个组件
Vue.component(TypeNav.name,TypeNav)
使用:
在需要使用的地方引用即可
不是全局组件,建好后在需要的页面注册
如:在homeIndex.vue引入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cgGhPurQ-1645519249992)(C:\Users\yang6\AppData\Roaming\Typora\typora-user-images\image-20220222131605575.png)]
使用:
或
其他同理,页面使用多个组件:
3.1.3 POSTMAN测试接口