banner
NEWS LETTER

Vue框架

Scroll down

Vue框架

Vue基础

Vue简介

​ 是一款用于构建用户界面的渐进式框架

安装

vue下载地址:https://unpkg.com/vue@3.2.36/dist/vue.global.js

安装脚手架vite

1
2
3
4
5
6
npm init vite@latest vue-begin -- -- template vue

运行
cd 项目名
npm install
npm run dev

安装jquery库

1
npm install jquery --save-dev

安装bootstrap

1
npm install  --save-dev bootstrap@3.4.1

安装Element-UI

要安装 Element UI,需要先确保你的项目使用了 Vite 作为构建工具。如果还没有安装 Vite,可以在终端中运行以下命令:

1
npm install -g vite

然后,在你的项目目录下打开终端,运行以下命令来安装 Element UI:

1
npm install element-plus --save

安装完成后,在 main.js 文件中引入 Element UI:

1
2
3
4
5
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css';

createApp(App).use(ElementPlus).mount('#app')

现在,Element UI 已经被成功地安装并引入到你的项目中了。

安装并使用jquery

在vite中不具有使用jquery的配置,因此只能通过插件将webpack的jquery注入

1
2
安装插件
npm i jquery @rollup/plugin-inject -S

基础设置

配置端口

在vite.config中配置

1
2
3
4
5
6
export default defineConfig({
plugins: [vue()],
server: {
port: 7070
}
})

连接拦截

拦截局域网中想要连接所有地址

1
2
3
4
5
6
7
export default defineConfig({
plugins: [vue()],
server: {
port: 7070,
host: "0.0.0.0"
}
})

配置代理

为了避免前后端服务器联调时, fetch、xhr请求产生跨域问题,需要配置代理,同样是修改项目根目录下vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
port: 7070,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
})

vue的特性

Vue框架的特性主要体现在两个方面

  1. 数据驱动视图

​ 在使用vue的页面中,vue会监听数据的变化,从而自动重新渲染结构

  1. 双向数据绑定

vue基本使用

  1. 导入vue.js的script的脚本文件

  2. 在页面中声明一个将要被vue所控制的DOM区域

  3. 创建vm实例化对象

1
2
3
4
5
6
7
8
9
10
11
//Vue应用通过createApp函数
const app = Vue.createApp({
data() { //data 选项是一个函数。Vue 在创建新组件实例的过程中调用此函数
return {
message: 'Hello Vue!!'
}
}
})
app.mount('#wai')
//使用.mount将app挂载应用
//一个应用需要被挂载到一个 DOM 元素中,以上代码使用 mount('#wai') 将 Vue 应用 app 挂载到 <div id="wai"></div> 中

创建根组件(应用实例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { createApp } from 'vue'

Const const=createApp({
//根组件选项
})



// 创建一个Vue 应用
const app = Vue.createApp({})

// 定义一个名为 runoob 的新全局组件
app.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
//引入根节点
app.mount('#app')

我们传入的createApp实际上是一个根组件,其他的所有组件都隶属于这个根组件

模板语法

文本插值

最基本的格式就是用双花括号

1
2
3
4
5
6
7
8
9
10
11
<span>Message: {{ msg }}</span>


export default{
name:'HelloWorld',
data(){
return{
msg:"看见我就对了"
}
}
}

插入原始HTML

使用v-html插入原始html

1
2
3
4
5
6
7
8
9
10
11
<p v-html="link"></p>


export default{
name:'HelloWorld',
data(){
return{
link:"<a href='http://www.baidu.com'>百度</a>"
}
}
}

Attribute 绑定

可以动态更改id、class和自定义名称 :id :class

1
2
3
4
5
6
7
8
9
10
11
<h1 :id="hao">{{ msg }}</h1>

export default{
name:'HelloWorld',
data(){
return{
msg:"看见我就对了",
hao:"ma"
}
}
}

使用js表达式

vue已经全面支持js完整表达式,可以在双括号中进行js运算和判断

1
2
3
4
5
6
7
{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div :id="`list-${id}`"></div>

v-bind属性绑定

​ v-bind指令主要用于响应式的更新html的属性

​ 一般我们要想在元素节点的属性上绑定vue的data数据是不可以直接使用双花括号插入值语法来使用

​ 如果我们想让dom属性节点与data数据绑定响应就需要使用v-bind指令

例如:为h1添加title属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div>
<h1 :title="tit">这是一个h1</h1>
</div>

</body>
<script src="../js/vue3.js"></script>
<script>
const app=Vue.createApp({
data(){
return{
tit:"abcd"
}
}
})
app.mount("div")
</script>

例如:添加class类active

1
2
3
4
5
6
7
8
9
10
11
12
<div class="static" :class="{ active: isActive, 'text-danger': hasError }"></div>

data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
}

则等同于class="static isActice"

条件渲染

v-if

只有当v-if条件为真时才进行渲染,否则不显示

1
2
3
4
5
6
7
8
9
10
<h1 v-if="flag">Vue is awesome!</h1>

export default{
name:'HelloWorld',
data(){
return{
flag:true
}
}
}

v-else

用于为v-if设置另一个选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button @click="awesome = !awesome">Toggle</button>

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>


export default{
name:'HelloWorld',
data(){
return{
flag:true
}
}
}

v-show和v-if的区别

v-if在设置false之后是见不到这个DOM元素的,而v-show则会相当于加了display属性none一样

v-for列表渲染

用v-for将一个数组映射为一组元素

v-for指令需要使用item in items形式的特殊语法,其中items是源数据数组,而item则是被迭代的数组元素的别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<ul>
<li v-for="item in aaa" :key="item.id">
{{item.title}}
</li>
</ul>


export default{
name:'HelloWorld',
data(){
return{
aaa:[{
id:1,
title:"第一个列表"
},{
id:2,
title:"第二个列表"
},{
id:3,
title:"第三个列表"
}]
}
}
}

例子:点击添加数据

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<body>
<div id="center">
<button @click="add">添加</button>
<button @click="del">删除</button>
<table>
<tr>
<td>班级</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
</tr>
<tr v-for="item in students">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.sex}}</td>
</tr>
</table>
</div>
</body>
<script src="../js/vue3.js"></script>
<script>
window.onload = function () {
const app = Vue.createApp({
data() {
return {
students: [{
id: '001',
name: "alice",
age: 18,
sex: 'female'
},
{
id: '002',
name: "marry",
age: 19,
sex: 'female'
},
{
id: '003',
name: "json",
age: 20,
sex: 'male'
}]
}
},
methods: {
add() {
var user = {
id: '004',
name: '张三',
age: '21',
sex: '男'
}
this.students.push(user) //添加
},
del(){
this.students.pop() //删除
}
}

})
app.mount("#center")
}


</script>

事件处理

使用@+事件进行绑定,methods里面写函数

1
2
3
4
5
6
7
8
9
10
11
<button @click="dianji">按钮</button>
<button @click="++num">按钮{{num}}</button>

export default{
name:'HelloWorld',
methods:{
dianji(){
num+=1
}
}
}

表单输入绑定

v-model设置表单双向绑定(输入什么就获取什么),v-model=”huoqv.lazy”在失去焦点时获取内容 .number自动将输入的内容转化为数字 .trim自动去除两端的空格

1
2
3
4
5
6
7
8
9
10
11
<input type="text" v-model="huoqv">
<p>{{huoqv}}</p>

export default{
name:'HelloWorld',
data(){
return{
huoqv:""
}
}
}

事件处理

事件修饰符

  • .stop:点击事件将停止传递
  • .prevent:点击超链接之类不再重新加载
  • .self:当有多个父级子级时只有点击它本身才回触发
  • .capture:谁有该事件修饰符,就先触发谁
  • .once:只触发一次
  • .passive:事件的默认行为,立即执行无需等待
1
2
3
4
5
6
7
<div id="app">
<div style="width: 500px; height: 500px; background: red;" @click.stop="clickdiv1">
<div style="width: 300px; height: 300px; background: blue;" @click.stop="clickdiv2">

</div>
</div>
</div>

计算属性

用于处理一些复杂逻辑运算

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
<body class="body">
<input type="text" v-model=str1 ><br>
<input type="text" v-model=str2 >
<h2>{{hn}}</h2>
</body>

<script>
const app = Vue.createApp({
data() {
return {
str1: '',
str2: ''
}
},
computed: {
hn: {
get() {
return (this.str1.toUpperCase() + " " + this.str2.toUpperCase()).split('').reverse().join('');
},
set(newnum){
var new1 = newnum.split(" ")
this.str1=new1[0]
this.str2=new1[1]
}
}

}
})
app.mount(".body")
</script>

监听属性

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
34
35
36
	<body>
<div id="div1">
<h2>今天天气是{{info}}</h2>
<button @click="changWeacher">切换天气</button>
<h2>今天天气是{{weather}}</h2>
<button @click="changWeacher">切换天气</button>
</div>
</body>
<!-- 侦听属性watch:
1.当被侦听的属性发生改变时,会自动去执行回调属性 -->
<script>
const con=Vue.createApp({
data(){
return{
isHot:true,
weather:""
}
},
methods:{
changWeacher(){
this.isHot=!this.isHot
}
},
watch:{
isHot:{
// 当isHot值改变时自动调用下面的方法
handler(newVal,oldVal){
this.weather=newVal?"炎热":"凉爽"
},
// 初始化时,让handler先执行一次
immediate:true
}
}
})

con.mount("#div1")

过滤器filter(vue3弃用)

过滤器作用

​ 用来格式化数据的一个函数。过滤器不会修改原始数据,它的作用是过滤数据,就是对数据进行加工处理并返回处理后的数据,比如做一些数据格式上的修改,状态修改等。

过滤器分为两种

​ 组件内的过滤器(组件内有效)

​ 全局过滤器(所有组件共享)

定义过滤器

  • 第一个参数是过滤器的名字

  • 第二个参数是过滤器的功能函数(若不定义vue就不知道这个字符串是什么,有什么作用)

    过滤器的功能函数

    • 声明function(data,argv1,argv2…){}
    • 第一个参数是传入的要过滤的数据,即调用时管道符左边的内容
    • 第二个参数开始就是调用过滤器的时候传入的参数

过滤器的使用

  • 先注册,后使用
  • 组件内 filters:{过滤器:fn} fn内通过return返回最终的数据
  • 全局Vue.filter(‘过滤器名’,fn) fn内通过return返回最终的数据
  • 使用{{数据 | 过滤器名}} 管道符 | 右边是过滤器名称,即文本功能函数
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

<template>
<div class="test">
<p>{{price}}</p>
<p>{{price | filter_addPricePrefix}}</p>
<p>{{price | filter_addPricePrefix |filter_addPriceSuffix}}</p>
</div>
</template>

<script>
export default {
data() {
return {
price: 100
};
},
filters: {
filter_addPricePrefix(value) {
return "¥" + value;
},
filter_addPriceSuffix(value) {
return value + "元";
}
}
};
</script>

<style lang="scss" scoped>
.test {
color: black;
}
</style>

过渡和动画

过渡

​ 进入(显示,创建)

​ v-enter-from 进入前

​ v-enter-active 进入中

​ v-enter-to 进入后

​ 离开(隐藏,移除)

​ v-leave-from 离开前

​ v-leave-active 离开中

​ v-leave-to 离开后

这里的v指的是默认前缀如果transition标签中设置了name属性可替代为name-enter-from

gd

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
34
<head>
<style>
.dong-enter-active{
transition: all .3s ease;
}
.dong-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}隐藏中的过度
.dong-enter-from, .dong-leave-to{
transform: translateX(10px);
opacity: 0;
}
</style>
</head>
<body>
<div id="databinding">
<button v-on:click="show = !show">点我</button>
<transition name="dong">
<p v-if="show">动画实例</p>
</transition>
</div>
</body>
<script src="../js/vue3.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data(){
return{
show: true
}

}
});
vm.mount("body")
</script>

动画

dh

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
34
35
36
37
38
39
40
	<style>
.dong-enter-active {
animation: bounce-in .5s;
}
.dong-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
</style>
</head>
<body>
<div id="databinding">
<button v-on:click="show = !show">点我</button>
<transition name="dong">
<p v-if="show">闫雨萌</p>
</transition>
</div>
</body>
<script src="../js/vue3.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data(){
return{
show: true
}

}
});
vm.mount("body")
</script>

通过自定义动画

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
</head>
<body>
<div id = "databinding">
<button v-on:click = "show = !show">点我</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">闫雨萌</p>
</transition>
</div>
</body>
<script src="../js/vue3.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data(){
return{
show: true
}

}
});
vm.mount("body")
</script>
</html>

结合Velocity.js实现动画

QQ录屏20221121172034

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
34
35
36
37
38
39
40
41
42
43
44
45
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>

</head>

<body>
<div>
<button @click="show=!show">点击</button>
<transition @before-enter="beforeEnter" @enter="enter" @leave="leave" v-bind:css="false">
<p v-if="show">文字动画效果</p>
</transition>
</div>

</body>

<script>
const app=Vue.createApp({
data(){
return{
show:false
}
},
methods:{
beforeEnter(el){
el.style.opacity=0
el.style.transformOrigin='left'
el.style.color='red'
},
enter(el,done){
Velocity(el,{opacity:1,fontSize:'1.4em'},{duration:300})
Velocity(el,{fontSize:'1em'},{complete:done})
},
leave(el,done){
Velocity(el,{translateX:'15px',rotateZ:'50deg'},{duration:300})
Velocity(el,{rotateZ:'100deg'},{loop:1})
Velocity(el,{rotateZ:'45deg',translateY:'30px',translateX:'30px',opacity:0},{complete:done})
}
//Velocity函数的第一个参数是DOM元素,第二个参数是用来传入css参数列表,第三个参数表示动画配置
}
})
app.mount("div")
</script>

组件基础

创建组件并赋值

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
<body>
<div id="app">
<button-counter></button-counter>
</div>
</body>

<script>

const app = Vue.createApp({

})
app.component('button-counter', {
data() {
return {
aaa:[{
title:"火锅"
},{
title:"烧烤"
},{
title:"小龙虾"
},{
title:"牛排"
}]
}
},
template: `
<ul :style="'background-color:#80c7ec'">
<li v-for='item in aaa'>{{item.title}}</li>
</ul>`
})
app.mount("#app")

Vue单文件组件,是一种特殊的文件格式,它允许将vue组件的模板、逻辑样式封装在单个文件中

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
34
35
36
37
<script >
import learn from './components/learn.vue' //this

export default{
name:"App",
components: { learn } //this
}
</script>

<template>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
<HelloWorld msg="Vite + Vue" />
<learn/> <!--this-->
</div>

</template>

<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

加载组件

第一步:引入组件 import learn from ‘./components/learn.vue’

第二步:挂载组件 export default{
name:”App”,
components: { learn } //this
}

第三步:显示挂件

Props组件交互

组件和组件之间是存在交互的,否则完全没有关系

props是你可以在组件上注册的一些自定义attribute

props交互示意图:

QQ截图20221124213859

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
34
35
36
37
38
39
App.vue
<learn :title="title" :names="names"/>

<script>
name:"App",
components: { learn },
data(){
return{
title:"我是一个标题",
names:["LiMing","Jenny","Danny"]
}
}
</script>



learn.vue
<template>
<p>{{title}}</p>
</template>

<script>
export default{
name:"learn",
props:{
title:{
type:String, <!--数组和对象必须使用函数进行返回-->
default:""
},
names:{
type:Array,
default:function(){
return []
}
}
}
}
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
<div id="aaa">
<parent name="张三"></parent>
</div>

</body>
<script src="../js/vue3.js"></script>
<script>
const app = Vue.createApp({

})
app.component("parent",{
props:['name'],
template:'<h4>我的名字是{{name}}</h4>'
})

app.mount("#aaa")
</script>
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
<body>
<ul id="aaa" style="background-color:#80c7ec">
<site v-for="lis in lise" :title="lis.title"></site>
</ul>

</body>
<script src="../js/vue3.js"></script>
<script>
const app = Vue.createApp({
data(){
return{
lise:[
{title:"火锅"},
{title:"烧烤"},
{title:"小龙虾"},
{title:"啤酒"}
]
}

}
})
app.component("site",{
props:['title'],
template: `<li>{{title}}</li>`
})

app.mount("#aaa")
</script>

自定义事件组件交互

自定义事件可以在组件中反向传递数据,prop可以将数据从父组件传到子组件,那么反向将数据从父组件传到子组件就可以使用自定义事件$emit

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
34
35
36
37
38
39
learn.vue
<template>
<button @click="pao">点击</button>
</template>

<script>
export default{
name:"learn",
data(){
return{
message:"我是learn数据"
}
},
methods:{
pao(){
this.$emit("run",this.message)
}
}
}
</script>


App.vue
<template>
<MyComponent @run="pao">
</template>


import MyComponent from './compents/MyComponent.vue'

export default{
name:"App",
components: { learn },
methods:{
run(date){
console.log(date)
}
}
}

slot插槽

默认插槽

​ 子类模板中定义一个slot插槽标签,父类使用组件时会自动将chacao自定义标签内部的标签替换掉子组件中的slot插槽标签

​ App.vue

1
2
3
4
5
6
7
8
<template>
<chacao>
<button>按钮</button>
</chacao>
<chacao>
<input type="text"/>
</chacao>
</template>

​ chacao.vue

1
2
3
4
5
6
7
8
9
10
<template>
<div>
<h2>我是content组件内容</h2>
<div><slot></slot></div>
</div>
</template>

<script>

</script>

具名插槽

​ 在子组件的插槽标签slot中设置name属性,当父组件替换子标签中的slot会通过template标签中的v-slot属性去寻找对应的name值并完成对应的替换。

​ App.vue

1
2
3
4
5
6
7
8
9
10
<template>
<chacao>
<template v-slot:button>
<button>按钮</button>
</template>
<template v-slot:input>
<input type="text">
</template>
</chacao>
</template>

​ changcao.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<h2>我是content组件内容</h2>
<div>
<slot name="button">
<p></p>
</slot>
</div>

<div>
<slot name="input"/>
</div>
</div>
</template>

<script>

</script>

而没有被设置名字的则会通过设置默认值来进行被父组件的替换

image-20221125173349689

插槽作用域

插槽就是子组件中的提供给父组件使用的一个占位符,用slot表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的slot标签。插槽显不显示显示什么结构是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制

App.vue

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
34
35
36
37
38
39
40
41
42
<script>
import chacao from './components/chacao.vue'
export default {
name: "App",
components: {chacao},
}

</script>

<template>
<div>
<chacao>
<template v-slot:default="chide"> //v-slot:default用来接收子类传来的数据
<h2>你可以选择吃东西</h2>
<ul>
<li v-for="item in chide.eat">{{item}}</li>
</ul>
</template>
</chacao>
<chacao>
<template v-slot:default="wande">
<h2>你可以选择看玩游戏</h2>
<ul>
<li v-for="item in wande.game">{{item}}</li>
</ul>
</template>
</chacao>
<chacao>
<template v-slot:default="wande">
<h2>你可以选择看电影</h2>
<ul>
<li v-for="item in wande.movie">{{item}}</li>
</ul>
</template>
</chacao>
</div>

</template>

<style>

</style>

chacao.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div><slot :eat="eat" :game="game" :movie="movie"></slot></div>

</template>

<script>
export default{
data(){
return{
eat:['火锅','烧烤','小龙虾','牛排'],
game:['GTA5','地平线','看门狗','使命召唤'],
movie:['盗梦空间','战狼','肖申克的救赎','阿甘正传']
}
}
}
</script>

跨级通信

在组建的嵌套中如果单纯使用props会变得非常复杂,因此我们可以使用provide和inject

App.vue

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
<script>
import zi from './components/zi.vue'
export default {
name: "App",
components: {chacao,zi},
data(){
return{
message:"parent",
obj:{
message:"父组件的信息"
}
}
},
provide(){
return{
message:()=>this.message //传走message数据
}
}
}

</script>

<template>
<div>
<zi></zi>
<button @click="message='你好'">改变message</button>
<h2>{{obj.message}}</h2>
</div>
</template>

zi.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<sun></sun>
</div>
</template>

<script>
import sun from './sun.vue'
export default{
components:{
sun
}
}
</script>

<style>

</style>

sun.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<h2>我是sun组件{{message()}}</h2> <!--this-->
</div>
</template>

<script>
export default{
data(){
return{
}
},
inject:['message'] //接收message方法传给h2
}
</script>

<style>

</style>

image-20221126095934014点击后:image-20221126095949170

生命周期(钩子函数)

给了用户在不同阶段添加要执行的函数

1、beforeCreate(创建前)

表示实例完全被创建出来之前,vue 实例的挂载元素$el和数据对象 data 都为 undefined,还未初始化。

2、created(创建后)

数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在 。

3、beforeMount(挂载前)

vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中。data.message 未替换。

4、mounted(挂载后)

vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。

5、beforeUpdate(更新前)

当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。

6、updated(更新后)

当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。

7、beforeDestory(销毁前)

组件销毁之前调用 ,在这一步,实例仍然完全可用。

8、destoryed(销毁后)

组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,但 dom 结构依然存在。

Vue引入第三方

安装swiper

1
安装指定版本:npm install --save swiper@8.4.1

基础实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<Swiper>
<swiper-slide><img src="../../img/梅西.jpg"></swiper-slide>
<swiper-slide><img src="../../img/C罗.jpg"></swiper-slide>
<swiper-slide><img src="../../img/德布劳内.jpg"></swiper-slide>
<swiper-slide><img src="../../img/莱万多夫斯基.jpg"></swiper-slide>
<swiper-slide><img src="../../img/内马尔.jpg"></swiper-slide>
<swiper-slide><img src="../../img/萨拉赫.jpg"></swiper-slide>
</Swiper>
</template>


<script>
import 'swiper/css'
import { Swiper, SwiperSlide } from 'swiper/vue'
export default {
name:"carousel",
components: {
Swiper,
SwiperSlide,
}
};
</script>

添加分页效果

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
<template>
<Swiper :modules="modules" :pagination="{clickable:true}">
<swiper-slide><img src="../../img/梅西.jpg"></swiper-slide>
<swiper-slide><img src="../../img/C罗.jpg"></swiper-slide>
<swiper-slide><img src="../../img/德布劳内.jpg"></swiper-slide>
<swiper-slide><img src="../../img/莱万多夫斯基.jpg"></swiper-slide>
<swiper-slide><img src="../../img/内马尔.jpg"></swiper-slide>
<swiper-slide><img src="../../img/萨拉赫.jpg"></swiper-slide>
</Swiper>
</template>


<script>
import 'swiper/css'
import{ Pagination} from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css/pagination'
export default {
name:"carousel",
data(){
return{
modules:[Pagination]
}
},
components: {
Swiper,
SwiperSlide,
}
};
</script>

Axios网络请求

什么是Axios

​ Axios是一个基于promise的异步ajax请求库

安装

1
2
3
4
5
6
7
8
9
npm install --save axios

post请求参数是需要额外处理的
npm install --save querystring

data:qs.stringify({

})

引入

​ 在组件中引用:

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
34
35
36
37
<template>
<div>
{{aaa}}
</div>
</template>

<script>
import axios from "axios"


export default {
name:"carousel",
data(){
return{
aaa:""
}
},
mounted() { //挂载后执行
axios({
method:"get",
url:"/src/components/1.txt",
// data:qs.stringify({

// })
}).then(res=>{
this.aaa=res.data
})
}

//简写方法
mounted(){
axios.get("/src/components/1.txt").then(res=>{
this.aaa=res.data
})
}
};
</script>

​ 使用全局引用

1

vue路由

什么是路由

​ 可以让Vue.js构建单页应用实现不刷新跳转变得轻而易举

安装路由

1
npm install --save vue-router

引入、使用路由

​ 1.新建两个文件

1
2
3
4
5
6
7
8
9
10
HomeView.vue
<template>
<h1>首页</h1>
</template>


AboutView.vue
<template>
<h1>关于</h1>
</template>

​ 2.创建配置文件

​ index.js(在components文件夹中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//配置文件
import {createRouter,createWebHashHistory} from 'vue-router' //固定配置
import AboutView from './AboutView.vue' //文件1
import HomeView from './HomeView.vue' //文件2


//配置信息中需要页面的相关配置
const routes=[
{
path:"/about", //设置访问地址
component:AboutView //对应文件
}, {
path:"/home",
component:HomeView
},
]

const router=createRouter({
history:createWebHashHistory(), //可以替换为createWebHistory但是容易引起404所以需要后台配合
routes
})

export default router;

​ 3.在入口文件main.js中配置

1
2
3
4
5
6
7
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './luyou' //将第二步设置的配置文件导入

const app=createApp(App)
app.use(router).mount('#app') //.use使用router

​ 4.在页面中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
export default {
name: "App",
}

</script>

<template>
<div>
//router创建超链接,to属性用来指定路径和配置文件的path相匹配
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
//用来显示页面内容
<router-view></router-view>
</div>

</template>

<style>

</style>

路由传递参数

​ 1.新建两个文件

1
2
3
4
5
6
7
8
9
10
11
12
HomeView.vue
<template>
<h1>首页</h1>
<p>{{$route.params.ho}}</p> //获取路由中的参数
</template>


AboutView.vue
<template>
<h1>关于</h1>
<p>{{$route.params.ab}}</p>
</template>

​ 2.创建配置文件

​ index.js(在components文件夹中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//配置文件
import {createRouter,createWebHashHistory} from 'vue-router' //固定配置

//配置信息中需要页面的相关配置
const routes=[
{
path:"/about/:ab", //设置地址及附带参数 :ab
name:'about', //名字,可带可不带
component:()=>import('./AboutView.vue') //组件地址
}, {
path:"/:ho",
name:'home',
component:()=>import('./HomeView.vue')
}
]

const router=createRouter({
history:createWebHashHistory(), //可以替换为createWebHistory但是容易引起404所以需要后台配合
routes
})

export default router;

​ 3.在入口文件main.js中配置

1
2
3
4
5
6
7
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './luyou' //将第二步设置的配置文件导入

const app=createApp(App)
app.use(router).mount('#app') //.use使用router

​ 4.在页面中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script >
export default {
name: "App",
data() {
return {
aaa:prompt('请填写要显示的内容')
}
}
}

</script>

<template>
<div>
<router-link :to="/home/+aaa">首页</router-link> //动态绑定传递数据
<router-link to="/about/这里是关于">关于</router-link>
<router-view></router-view>
</div>

</template>

<style>

</style>

嵌套路由配置

​ 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
28
29
30
HomeView.vue
<template>
<h1>首页</h1>
<p>{{$route.params.ho}}</p>
<router-link to="/one">分页1</router-link>
<router-link to="/two">分页2</router-link>
<router-view></router-view>
</template>


AboutView.vue
<template>
<h1>关于</h1>
<p>{{$route.params.ab}}</p>
<router-link to="/about/us">关于我们</router-link>
<router-link to="/about/info">关于信息</router-link>
<router-view></router-view>
</template>


AboutInfo
<template>
<h3>关于信息</h3>
</template>


AboutUS
<template>
<h3>关于我们</h3>
</template>

​ 2.创建配置文件

​ index.js(在components文件夹中)

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
34
35
36
37
//配置文件
import {createRouter,createWebHashHistory} from 'vue-router'


//配置信息中需要页面的相关配置
const routes=[
{
path:"/about", //:ab添加参数
name:'about',
component:()=>import('./AboutView.vue'),
children:[{
path:"us",
component:()=>import("./AboutUS.vue")
},{
path:"info",
component:()=>import("./AboutInfo.vue")
}]
}, {
path:"/",
name:'home',
component:()=>import('./HomeView.vue'),
children:[{ //通过children嵌套,中的path不要加/
path:"one",
component:()=>import("./AboutUS.vue")
},{
path:"two",
component:()=>import("./AboutInfo.vue")
}]
}
]

const router=createRouter({
history:createWebHashHistory(),
routes
})

export default router;

​ 3.在入口文件main.js中配置

1
2
3
4
5
6
7
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './luyou' //将第二步设置的配置文件导入

const app=createApp(App)
app.use(router).mount('#app') //.use使用router

​ 4.在页面中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script >
export default {
name: "App",
data() {
return {
aaa:prompt('请填写要显示的内容')
}
}
}

</script>

<template>
<div>
<router-link :to="/home/+aaa">首页</router-link> //动态绑定传递数据
<router-link to="/about/这里是关于">关于</router-link>
<router-view></router-view>
</div>

</template>

<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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<template>
<h2>page页面</h2>
<button @click="goPage">点击按钮跳转</button>
</template>
<script>
export default{
methods:{
goPage:function(){
// 跳转导航
this.$router.push("/")

if(123==123){
this.$router.push("/")
}
// 通过传递对象跳转
this.$router.push({path:"/about:654565"})
// 通过name名跳转
this.$router.push({name:"guanyv",params:{id:123546}})
// 设置带?的附加参数
this.$router.push({path:"/about",query:{name:"zhangsan"}})
}
}
}
</script>

<template>
<div>
<h1>关于</h1>
<router-link to="/about/us">关于我们</router-link>
<router-link to="/about/info">关于信息</router-link>
<router-view></router-view>
</div>

</template>



AboutView.vue
<script>
export default{
mounted(){
//在跳转页面可以通过this.$route.query.name拿取数据
console.log(this.$route.query.name);
}
}
</script>

替换、前进后退

1
2
3
4
5
6
7
8
// 替换当前位置
this.$router.replace({path:"/about",query:{name:"zhangsan"}})
// 前进
this.$router.forward()
this.$router.go(1)
// 后退
this.$router.back()
this.$router.go(-1)

命名路由和命名视图

指定某个地方分配怎样的路由

1.创建三个组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
shopTop.vue
<template>
<div>
<h3>shop的头部</h3>
</div>
</template>


shopCen
<template>
<div>
<h3>shop的中部</h3>
</div>
</template>


shopFoot
<template>
<div>
<h3>shop的尾部</h3>
</div>
</template>

2.在配置文件中指定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { createRouter, createWebHashHistory } from 'vue-router'
import tou from '../luyou/shopTop.vue'
import zhong from '../luyou/shopCen.vue'
import wei from '../luyou/shopFoot.vue'

//配置信息中需要页面的相关配置
const routes = [
{
path:"/shop", //当访问路径为/shop时将shopTop、shopChen、shopFoot渲染到指定位置
components:{
default:zhong, //当没有指定名字时,渲染zhong
tou,wei
}
}
]

const router = createRouter({
history: createWebHashHistory(),
routes
})

export default router;

3.页面上渲染App.vue

1
2
3
4
5
6
7
8
9
10
11
<template>
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link to="/tz">go to</router-link>
<router-view name="tou"></router-view> //指定渲染
<router-view></router-view> //默认渲染
<router-view name="wei"></router-view>
</div>

</template>

Vuex状态管理

状态管理可以理解成为更方便的管理组件之间的数据交互

1.下载Vuex

1
npm install vuex@next --save

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
28
29
30
31
32
import {createStore} from 'vuex'		//引入vuex
import axios from 'axios'

// Vuex的核心作用就是帮我们管理组件之间的状态
export default createStore({
// 所有的数据都放在这里
state(){
return{
count:0
}
},
//主要用来放需要复杂运算的数据
getters:{
getCounter(state){
return state.count>0 ? state.count : "内容小于0,不予显示"
}
},
//可以通过事件改变数据
mutations:{
addCounter(state,num){ //state表示上面定义的state对象
state.count+=num
}
},
//从外部拿取数据
actions:{
asyn({commit}){
axios.get("http://iwenwiki.com/api/generator/list.php").then(res=>{
commit("addCounter",res.data[0])
})
}
}
})

3.在入口文件中引入

1
2
3
4
5
6
7
8
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router/index'
import store from './store'

const app=createApp(App)
app.use(store).use(router).mount('#app')

4.在页面上使用

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>
<button @click="addClickHandle">点击功德+1</button>
<p>{{ $store.state.count }}</p>
<button @click="addas">点击得到进口功德</button>
</div>

</template>
<script >
// vuex提供的mapState快捷读取方式
import { mapState,mapGetter,mapActions} from 'vuex';
export default {
name: "App",
computed: {
//把各个数据和方法引入到这里
...mapState(['count']),
...mapGetters(['getCounter'])
...mapActions(["asyn"])
},
methods: {
addClickHandle() {
// 固定调用方式,可以选择添加或者不添加参数
this.$store.commit("addCounter",20) //使用store.commit方法调用mutations的addCounter函数
},
addas(){
this.$store.dispatch("asyn") //使用dispatch方法调用actions的asyn方法
}
}
}
</script>
<style>

</style>

image-20221130181737218

Other Articles