组件通信

父子组件/组件的嵌套

组件与组件之间是可以相互嵌套 环环相扣 那么这种关系我们就称之为 父子组件

父子组件的作用域

组件与组件之间是一个完整的独立的个体 他们之间的数据默认是不能相互使用

组件通信/组件传值

正向传值–父给子传值–props

props是一个属性 他可以接收组件外部的传值

语法:写在 data methods watch computed components 同级

props:[ 接收的变量1,接收的变量2,,,,,,,n]

子组件设置接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<!-- 2.使用props这个接受变量 -->
zizizizizizzz--{{ziprops}}
</div>
</template>

<script>
export default {
// 子组件需要接受父组件的数据 所以在子组件中设置props
// 来接受组件外部传递进来的数据
// 1.设置props来接受
props:["ziprops"]
}
</script>

<style>

</style>

父组件开始传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
fufufufufufuffuf
<!-- 3.在子组件被调用的地方 把props当成标签的属性进行传递 -->
<Zi v-bind:ziprops="futext"/>
</div>
</template>

<script>
import Zi from "./zi.vue"
export default {
components:{
Zi
},
data(){
return {
futext:"我是父组件的变量么么哒!!!!"
}
}
}
</script>

<style>

</style>

思考

我使用props完成正向传值 那么我父组件给子组件是不是可以传递任何数据类型的内容?

正向传值默认的时候可以传递任何的数据类型

props验证

因为默认情况下props可以接收任何数据类型的数据 子组件在接收数据之后处理可能会有一些问题

那么我们就可以在接收props的时候对数据进行验证 限制传递进来的数据格式与类型

语法:

props:{

​ 你接受的props变量:数据类型

​ 你接受的props变量:[数据类型1,数据类型2]

}

注意 props验证不会影响我们的显示结果 而是只会在控制台给我们开发者一个警告提示我们有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<div>
<!-- 2.使用props这个接受变量 -->
zizizizizizzz--{{ziprops+1}}
</div>
</template>

<script>
export default {
// 子组件需要接受父组件的数据 所以在子组件中设置props
// 来接受组件外部传递进来的数据
// 1.设置props来接受
// props:["ziprops","zibprops"]

// props验证
props:{
// ziprops:Number
// 不能为空的限制
ziprops:{
type:Number,
required:true
}
}
}
</script>

<style>

</style>

逆向传值–子给父传值

逆向传值默认是不被允许的(vue中没有专门的语法进行逆向传值)我们需要使用其他的方式来侧面的完成

$emit(自定事件名,数据) 自定义事件来完成

1.子组件通过事件(必须要通过事件触发才能传递)抛出一个自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<div>
zizizizizizzi
<!-- 1.通过事件来触发一个函数进行自定义事件的抛出 -->
<button @click="fun()">点我逆向传值</button>
</div>
</template>

<script>
export default {
data(){
return {
zitext:"我是子组件的数据!!!!"
}
},
methods:{
fun(){
// 2.使用自定义事件抛出数据
this.$emit("ziemit",this.zitext)
}
}
}
</script>

<style>

</style>

2.接受自定义事件获取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<div>
fufufuffufufufu
<!-- 3.在子组件被调用的时候绑定自定义事件 -->
<!-- 不加()因为加了在这里会被自动调用 -->
<Zi @ziemit="fun"/>
</div>
</template>

<script>
import Zi from "./zi.vue"
export default {
// 4.创建函数
methods:{
fun(val){
console.log("我是父组件",val)
}
},
components:{
Zi
}
}
</script>

<style>

</style>

ref逆向传值

ref绑定到组件之上就可以回去到子组件这个vueComponent组件 从而可以得到当前子组件的所有信息 已达到逆向传值的目的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
  <div>
      fu
      <Zi @ziemit="fun" ref="zi"/>
  </div>
</template>

<script>
import Zi from "@/components/zi.vue"
export default {
    components:{
        Zi
    },
    methods:{
        fun(val){
            console.log("我是父组件",val);
            console.log(this.$refs.zi);
        }
    }
}
</script>

<style>

</style>

同胞传值–兄弟组件传值

同胞传值使用—中央事件总线(eventbus)

中央事件总线 就是凌驾在两个兄弟组件之上的一个空的vue实例 通过这个空的vue实例建立一个在兄弟组件传递数据的桥梁

1.创建一个eventbus的文件夹用来容纳中央事件总线 并且创建

1
2
3
// 中央事件总线  就是一个凌驾在组件之上的空vue实例
import Vue from "vue"
export default new Vue

2.在组件中抛出数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
aaaaaaaaaaaaaaaaaaaaa
<button @click="fun()">点我传递数据</button>
</div>
</template>

<script>
// 1.引用中央事件总线
import eventbus from "@/eventbus"
export default {
methods:{
fun(){
// 2.开始抛出数据 使用$emit()自定义事件进行抛出
eventbus.$emit("zia","我是zia的数据么么哒")
}
}
}
</script>

<style>

</style>

3.在接收的组件中使用数据

$on() 监听实例上的自定义事件

$on(“你要监听的自定义事件”,(就是自定义事件的参数)=>{})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
bbbbbbbbbbbbbbbbbbb---{{text}}
</div>
</template>

<script>
// 1.引用中央事件总线
import eventbus from "@/eventbus"
export default {
data(){
return {
text:""
}
},
// 2.开始自动监听
mounted(){
eventbus.$on("zia",(val)=>{
console.log(val)
this.text=val
})
}
}
</script>

<style>

</style>

跨层级传值–爷爷给孙子

vuex—统一状态(数据)管理工具 通过vuex可以把整个项目的数据进行统一的存储 不管是哪个组件用 只需要这个组件去vuex的仓库里面拿就可以了 不需要传统组件传值的那些复杂度

因为组件数据传递是单向数据流

vuex脚手架创建

在下载项目的时候 选中vuex即可

store文件夹 就是用来存放vuex的内容

vuex state

state就是数据源 存放vuex数据的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {//数据源 就是vuex中所有的数据都存在state
text:"字符串",
num:6666,
bool:true,
arr:[111,2222,3333,444],
obj:{
name:"xixix"
}
},
mutations: {
},
actions: {
},
modules: {
}
})

使用方式1

在你想用的地方直接使用 this.$store.state.xxx

1
2
3
4
5
<template>
<div class="about">
<h1>This is an about page----{{this.$store.state.num}}</h1>
</div>
</template>

使用方式2

使用计算属性来读取state中的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div class="about">
<h1>This is an about page----{{this.$store.state.num}}</h1>
{{newnum}}
</div>
</template>
<script>
export default{
computed:{
// 计算属性方式取值
newnum(){
return this.$store.state.num
}
}
}

</script>

vuex mutations

vuex中不能直接使用=给数据修改值

vuex中修改数据 必须使用mutations(是一个属性 在它里面是一个个的修改方法)

如果在页面中要触发mutations 那么 使用this.$store.commit()来进行触发

组件内使用commit来触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1>修改vuex的数据---{{ this.$store.state.num }}</h1>
<button @click="fun()">点我修改num</button>
</div>
</template>

<script>
export default {
methods: {
fun() {
// 触发vuex的mutations的修改
// this.$store.commit("你要触发的mutations的名字",传递的参数可选)
this.$store.commit("xiaoming", { text: "我是数据" });
},
},
};
</script>

<style>
</style>

vuex中创建对应的mutations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {//数据源 就是vuex中所有的数据都存在state
text:"字符串",
num:6666,
bool:true,
arr:[111,2222,3333,444],
obj:{
name:"xixix"
}
},
mutations: {
// state就是上面的数据源
// payload 载荷 作用就是接收commit 的第二个参数
xiaoming(state,payload){
state.num=payload.text
}
},
actions: {
},
modules: {
}
})

扩展–vuex数据修改刷新丢失问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
created () {
//在页面加载时读取sessionStorage里的状态信息
//判断本地存储是否有指定数据 如果有
//那么就用replacestate方法替换当前的state
// 拿现有的值和本地存储存的旧值使用0bject.assign进行合并
if (sessionStorage.getItem("store") ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
}

//在页面刷新时将vuex里的信息保存到本地存储中里
window.addEventListener("beforeunload",()=>{
sessionStorage.setItem("store",JSON.stringify(this.$store.state))
})
},

vuex actions

他是vuex中的一个异步触发器 他的作用就是触发异步操作的

页面内通过dispatch()来触发action进行异步操纵的触发器 actions中就是一个个的方法 每个方法就是一个异步操纵

1.组件内使用dispatch触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div class="home">

<button @click="fun()">点我进行异步请求</button>
</div>
</template>

<script>


export default {
name: 'Home',
methods:{
fun(){
// 在vuex中使用dispatch触发acions
// this.$store.dispatch("actions的名字",{你传递的参数})
this.$store.dispatch("xiaoming",{key:"我是数据"})
}
}
}
</script>

2.在vuex中来创建actions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {},
    mutations: {},
    actions: {
        xiaoming() {
            console.log("我是触发异步操作的地方");
        }
    },
    modules: {}
})

vuex getters

他就是vuex的计算属性

计算属性 对data中的数据进行处理并且返回新的处理之后的结果 仅仅只能对当前组件生效

getters 作为vuex的计算属性 他是对state中的数据进行处理并且返回新的结果 他处理的数据可以在任何组件中进行使用

语法:

getters:{

​ 处理的新变量() {

​ return

​ }

}

编写getters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from 'vue'
import Vuex from 'vuex'
import phonem from "./module/phonem.js"
Vue.use(Vuex)

export default new Vuex.Store({
state: {
text:"abcdefghijk"
},
mutations: {
},
actions: {
},
getters:{//计算属性
newtext(state){
return state.text.toUpperCase()
}
},
modules: {
phonem
}
})

读取的时候

this.$store.getters.xxxx

1
<h1>{{this.$store.getters.newtext}}</h1>

vuex modules

通过模块 就是把原来写在一堆堆的vuex内容 分别拆分成一个个的小文件小模块 方便后期的维护与管理

1.在store文件夹下新建modules文件夹用来容纳模块

2.在模块文件中写入相关vuex属性(原来怎么写在模块中就怎么写)

1
2
3
4
5
6
7
8
9
10
11
12
13
let commitm={
state:{
num:987
},
mutations: {
// state就是上面的数据源
// payload 载荷 作用就是接收commit 的第二个参数
xiaoming(state,payload){
state.num=payload.text
}
},
}
export default commitm

3.在vuex的文件中 引用使用模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
// 1.把你要用的模块引进来
import homem from "./modules/homem.js"
import aboutm from "./modules/aboutm.js"
import commitm from "./modules/commitm.js"

export default new Vuex.Store({

modules: {
// 2.再使用
homem,
aboutm,
commitm
}
})

4.在页面中使用的时候因为使用了模块 所以在读取数据的时候就必须是 this.$store.state.模块名.xxxx

vuex的流程

我们把vuex进行modules的拆分 然后再组件中使用dispatch()来触发actions进行异步的触发 在其中进行数据请求 把请求来得数据 要通过 commit来调用mutations进行state的数据修改 从而在页面可以读取请求过来得state数据 同时我们也可以对state的数据进行计算属性的getters处理 已达到一条数据在不同位置可以展示不同的形态

前后端数据交互

前端后端

前端 数据展示

后端 数据处理

方式

原生方式

jqeury ajax

axios 是一个第三方的数据请求库 他是基于promise 二次封装XHR对象的一个数据请求库

1 下载:

npm install –save axios

2 在要使用的地方引用

import 起个名字 from “axios”

3.开始发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
<h1>初级写法</h1>
<button @click="fun()">点我请求数据</button>
</div>
</template>

<script>
import $http from "axios"
export default {
methods:{
fun(){
$http({
url:"http://www.weather.com.cn/data/cityinfo/101320101.html",
method:"get",//没有s
}).then((ok)=>{
cosnole.log(ok)
}).catch((err)=>{
console.log(err)
})
}
}
}
</script>

<style>

</style>

数据请求封装与拦截器

拦截器

每次发送请求或者请求响应的时候 都会经过拦截器 才会进入到我们的程序(就是对我们的请求和响应进行发送前或者获取前的一个拦截 )

请求拦截

发送请求的时候会经过请求拦截 我们就可以在请求拦截上携带每次都要给后台的数据(用户的登录状态)

响应拦截

每次相应数据的时候都会经过响应拦截 (我们就可以在响应拦截的时候对我们的错误或者成功做出反应)

编写拦截器

1.在src下新建一个util文件夹(工具文件夹用来放置一些项目中辅佐工具库)再创建对应的文件用来容纳拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 引用axios
import axios from "axios"
let service=axios.create()
// 添加请求拦截器
service.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
service.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});

// 暴露
export default service

数据请求的封装

尽量符合最新的es标准promise来进行封装

1.在src下新建一个api的文件夹(就是容纳数据请求的)新建一个文件容纳封装的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1.引用拦截器
import service from "@/utils/service.js"
// 2.开始使用promise进行封装
let getlink=(url,method='get')=>{
// resolve成功
// reject失败
return new Promise((resolve,reject)=>{
// 就可以执行你所要封装的操纵
service.request({
url,
method
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}

// 3.暴露
export default getlink

使用封装的请求

1.在你想用的地方先引用 在使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script>
// 1.引用
import getlink from "@/api/getapi.js";
export default {
created(){
getlink("/api/data/cityinfo/101320101.html").then((ok)=>{
console.log(ok)
}).catch((err)=>{
console.log(err)
})
}
};
</script>

跨域

因为浏览器的安全机制 同源策略 不同端口不同域名不同协议 就会造成跨域

jsonp

代理跨域

代理:造成跨域的问题是浏览器的安全机制 因为有了这个安全机制我们才要解决跨域

​ 我现在不让浏览器帮我发送请求了 而是让我项目的服务器帮助我绕开浏览器发送请求

nginx反向代理

devServer代理跨域

devServer就是vue脚手架中那个内置的微型开发小服务器

1.在项目的根路径下 创建一个vue.config.js

2.写入如下内容

1
2
3
4
5
6
7
8
9
10
11
12
module.exports={
devServer: {
proxy: { //配置跨域
'/api': {
target: 'http://www.weather.com.cn/', //需要解决跨域的地址
pathRewrite: {
'^/api': ''
}
},
}
},
}

3.修改请求路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<div>
<h1>初级写法</h1>
<button @click="fun()">点我请求数据</button>
</div>
</template>

<script>
import $http from "axios"
export default {
methods:{
fun(){
$http({
// 修改名字
url:"/api/data/cityinfo/101320101.html",
method:"get",//没有s
}).then((ok)=>{
console.log(ok.data.weatherinfo)
}).catch((err)=>{
console.log(err)
})
}
}
}
</script>

<style>

</style>

4.千万不要忘了重启

动态组件

动态(自动变化 动态变化)组件

多个组件只有一个挂载点并且动态切换

语法

1.引用调用和之前使用组件是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
</div>
</template>
<script>
import One from "@/components/one.vue"
import Two from "@/components/two.vue"
import Three from "@/components/three.vue"
export default {
components:{
One,
Two,
Three,
}
}
</script>
<style>
</style>

3.使用 就需要使用动态组件的语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
<div>
<h1>动态组件 ---- 多个组件使用同一个挂载点</h1>

<button @click="el='One'">点我去one</button>
<button @click="el='Two'">点我去two</button>
<button @click="el='Three'">点我去three</button>
<!-- 设置挂载点 -->
<component :is="el"></component>
</div>
</template>

<script>
import One from "@/components/one.vue"
import Two from "@/components/two.vue"
import Three from "@/components/three.vue"
export default {
data(){
return {
el:"Three"
}
},
components:{
One,
Two,
Three,
}
}
</script>

<style>

</style>

动态组件或者路由切换的时候组件状态(内容数据)丢失问题

在上面的例子中如果我们在每个组件总添加一个输入框 并且输入内容 大家会发现当我们切换动态组件 或者切换路由的时候 组件中的状态内容会丢失

原理:

因为当我们每次切换组件的时候 vue都会创建一个新的实例

keep-alive

keep-alive可以用来保存组件中的状态内容

语法:

你想要保存状态的内容

如果要保存动态组件的状态

1
2
3
4
<!--使用keep-alive包裹挂载点-->
<keep-alive>
<component :is="el"></component>
</keep-alive>

如果要保存路由的状态 只需要用keep-alive包裹路由出口即可

1
2
3
<keep-alive>
<router-view/>
</keep-alive>

扩展keep-alive的属性与钩子

属性

在vue2.1以后 keep-alive就给我们添加了两个新的属性

include 你要缓存谁

1
2
3
<keep-alive include="One">
<component :is="el"></component>
</keep-alive>

exclude你不想缓存谁

1
2
3
<keep-alive exclude="Two">
<component :is="el"></component>
</keep-alive>

如果我同时写了include与exclude怎么办?先执行谁?

exclude的优先级大于include

钩子函数

activated

在进入被keep-alive管理的组件的时候触发

deactivated

在离开被keep-alive管理的组件的时候触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
我是机票的组件
<input type="text"> <input type="text"> <input type="text">
</div>
</template>
<script>
export default {
activated(){
console.log("进入被keep-alive管理的组件时候生效")
},
deactivated(){
console.log("离开被keep-alive管理的组件时候生效")
}
}
</script>
<style>
</style>

nextTick原理与使用场景

Vue中数据修改之后,页面的dom不是立即改变更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
  <div class="about">
    <h1>vue中数据修改之后,页面的dom不是立即修改更新的</h1>
    <h2 ref="demoh">{{text}}</h2>
    <button @click="fun()">点我修改数据</button>
  </div>
</template>
<script>
export default {
  data(){
    return{
      text:"我是数据"
    }
  },
  methods:{
    fun(){
      this.text="我变了"
      //下面打印的数据  得到的结果是原始数据而不是修改之后的数据
      console.log(this.$refs.demoh.innerText);
    }
  }
}
</script>

vue中的异步说明

简单的来说 vue在修改数据之后 视图是不会立刻更新数据的 而是等待着所有的数据都修改完成之后 然后再统一的进行数据的更新

原理流程:

1.vue修改数据是一个同步任务 这些同步任务都在线程的主轴上进行 形成了一个执行栈 但是在这个过程中并没有进行dom的操纵

2.vue会开启一个异步的列队 把所有修改之后的结果缓存起来

3.同步修改的任务执行完了 这个时候才开始进行dom的更新

问题

那么既然vue在修改完数据之后dom不是立即更新 那么我们如何得到修改完之后的dom内容???

nextTick

就是等待dom加载完毕之后立即执行

语法:

nextTick(()=>{

dom加载完毕之后立即执行

})

应用场景

1.我想在created中得到dom的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
  <div>
    <h1 ref="demoh">我是内容</h1>
  </div>
</template>

<script>
export default {
  created(){
    //默认情况下  因为当前钩子是vue实例创建完成并没有渲染dom所以会报错
    // console.log(this.$refs.demoh.innerText);
    this.$nextTick(()=>{
      //这个回调函数会在dom加载完毕后立即执行
      console.log(this.$refs.demoh.innerText);
    })
  }

}
</script>

<style>
 
</style>

场景2.我想在修改完数据之后 立即得到改变之后的dom内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
  <div class="about">
    <h1>vue中数据修改之后,页面的dom不是立即修改更新的</h1>
    <h2 ref="demoh">{{text}}</h2>
    <button @click="fun()">点我修改数据</button>
  </div>
</template>
<script>
export default {
  data(){
    return{
      text:"我是数据"
    }
  },
  methods:{
    fun(){
      this.text="我变了"
      //下面打印的数据  得到的结果是原始数据而不是修改之后的数据
      // console.log(this.$refs.demoh.innerText);
      this.$nextTick(()=>{
        console.log(this.$refs.demoh.innerText);
      })
    }
  }
}
</script>

项目的打包

1.使用npm run build来实现打包 会发现项目的根路径下出现了一个dist文件夹 (就是打包之后的内容)

但是我们直接运行这个文件夹下的index.html会发现页面什么都没有而且出现了很多报错

1
2
3
4
5
6
7
8
9
10
11
Refused to apply style from 'http://127.0.0.1:5500/css/app.5c9713c3.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

app.7ab044df.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)

chunk-vendors.9ea14b12.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)

index.html:29 Live reload enabled.

about.74c28bb4.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)

:5500/favicon.ico:1 Failed to load resource: the server responded with a status of 404 (Not Found)

原因是因为打包之后默认找不到打包的静态资源路径

2.修改项目的静态资源路径

在项目的根路径下创建一个vue.config.js文件,写入如下内容

1
2
3
4
module.exports = {
    //修改静态资源路径
    publicPath: "./",
}

3.修改路由模式为hash模式

1
2
3
4
5
const router = new VueRouter({
    mode: 'hash',
    base: process.env.BASE_URL,
    routes
})