Vue
Vue
官方文档:Vue.js - 渐进式 JavaScript 框架 | Vue.js
Vue API 风格
选项式 API 和 组合式 API
Vue 开发前的准备
nodejs的安装
创建vue项目
npm init vue@latest
cnpm install
npm run dev
开发环境:Vscode+Vue-Offical(插件)
Vue 项目目录结构
.vscode #VSCode工具的配置文件夹
node_modules #Vue项目的运行依赖文件夹
public #资源文件夹
src #源代码文件夹
.gitignore #Git文件
index.html #入口HTML文件
package.json #信息描述文件
README.md #注释文件
vite.config.js #Vue配置文件
模板语法
<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ hello }}</p>
</template>
<script>
export default {
data() {
return {
msg: "神奇的语法",
hello: "Hello,World!"
}
}
}
</script>
<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ hello }}</p>
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'YES' : 'NO' }}</p>
<p>{{ message.split("").reverse().join("") }}</p>
</template>
<script>
export default {
data() {
return {
msg: "神奇的语法",
hello: "Hello,World!",
number: 10,
ok:true,
message: "大家好"
}
}
}
</script>
原始HTML:插入 HTML
<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ hello }}</p>
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'YES' : 'NO' }}</p>
<p>{{ message.split("").reverse().join("") }}</p>
<p v-html = "rawHtml"></p>
</template>
<script>
export default {
data() {
return {
msg: "神奇的语法",
hello: "Hello,World!",
number: 10,
ok:true,
message: "大家好",
rawHtml:"<a href='http://baidu.com'>百度</a>"
}
}
}
</script>
属性绑定
双大括号不能再 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令,可以使用: 替代。
如果绑定的值为 NULL 或 Undefined,那么绑定对象会被移除。
<template>
<div v-bind:id = "dynamicId" v-bind:class = "dynamicClass">测试</div>
</template>
<script>
export default {
data() {
return {
dynamicClass: "appclass",
dynamicId: "appid"
}
}
}
</script>
<style>
.appclass {
color: red;
font-size: 30px;
}
</style>
如果想设置按钮是否可以点击
<template>
<button :disabled="isButtonDisable">按钮</button>
</template>
<script>
export default {
data() {
return {
isButtonDisable: false,
}
}
}
</script>
一个对象绑定多个值:
<template>
<div v-bind:id = "dynamicId" v-bind:class = "dynamicClass">测试1</div>
<button :disabled = "isButtonDisable">按钮</button>
<div v-bind = "objectOFAtters">测试2</div>
</template>
<script>
export default {
data() {
return {
dynamicClass: "appclass",
dynamicId: "appid",
isButtonDisable: false,
objectOFAtters: {
class: "appclass",
id: "appid",
}
}
}
}
</script>
<style>
.appclass {
color: red;
font-size: 30px;
}
</style>
条件渲染
v-if
<template>
<h3>条件渲染</h3>
<div v-if = "flag">你能看见我么</div>
<div v-else>那你还是看看吧</div>
<div v-if = "type === 'A'"> A </div>
<div v-else-if = "type === 'B'"> B </div>
<div v-else-if = "type === 'C'"> C </div>
<div v-else> Not A/B/C </div>
</template>
<script>
export default {
data() {
return {
flag: true,
type: "B",
}
}
}
</script>
v-show
<template>
<h3>条件渲染</h3>
<div v-if = "flag">你能看见我么</div>
<div v-else>那你还是看看吧</div>
<div v-if = "type === 'A'"> A </div>
<div v-else-if = "type === 'B'"> B </div>
<div v-else-if = "type === 'C'"> C </div>
<div v-else> Not A/B/C </div>
<div v-show = "flag">你能看见我吗</div>
</template>
<script>
export default {
data() {
return {
flag: true,
type: "B",
}
}
}
</script>
v-show 有较高的渲染开销,v-if 有较高的切换开销。
列表渲染
<template>
<h3>列表渲染</h3>
<p v-for = "item in names">{{ item }}</p>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "Hello", "IT"]
}
}
}
</script>
也可以改为 "item of names"
渲染对象:
<template>
<h3>列表渲染</h3>
<p v-for = "item in names">{{ item }}</p>
<div>
<p v-for="(value, key, index) in userInfo">{{ value }} - {{ key }} - {{ index }}</p>
</div>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "Hello", "IT"],
userInfo: {
name: "iwen",
age: 20,
sex: "男",
}
}
}
}
</script>
通过 Key 管理状态
为了给 Vue 一个提示,一边它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你需要为伟哥元素对应的块提供一个唯一的 Key
<template>
<h3>Key 属性添加到 v-for 中</h3>
<p v-for="(item, index) in names" :key = "index"> {{ item }}</p>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "Hello", "World"],
}
}
}
</script>
事件处理
v-on 可以简写为 @
内联事件处理器:用于简单的事件
<template>
<h3>内联事件处理器</h3>
<button v-on:click="count++">Add</button>
<p>{{ count }}</p>
</template>
<script>
export default {
data() {
return {
count: 0,
}
}
}
</script>
方法事件处理器
<template>
<h3>方法事件处理器</h3>
<button v-on:click="addCount">Add</button>
<p>{{ count }}</p>
</template>
<script>
export default {
data() {
return {
count: 0,
}
},
methods: {
addCount() {
// 读取到data里面的数据的方案
this.count ++
}
}
}
</script>
事件传参
<template>
<h3>事件传参</h3>
<button v-on:click="addCount">Add</button>
<p>{{ count }}</p>
</template>
<script>
export default {
data() {
return {
count: 0,
}
},
methods: {
// event对象
addCount(e) {
e.target.innerHTML = "Add" + this.count
this.count ++
}
}
}
</script>
<template>
<h3>事件传参</h3>
<button v-on:click="addCount('hello')">Add</button>
<p>{{ count }}</p>
</template>
<script>
export default {
data() {
return {
count: 0,
}
},
methods: {
// event对象
addCount(msg) {
// e.target.innerHTML = "Add" + this.count
console.log(msg)
this.count ++
}
}
}
</script>
<template>
<h3>事件传参</h3>
<p @click = "getNameHandler(item)" v-for = "(item, index) in names" :key = "index"> {{ item }}</p>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "ime", "frank"]
}
},
methods: {
getNameHandler(name) {
console.log(name);
}
}
}
</script>
事件修饰符
<template>
<h3>事件修饰符</h3>
<a @click="clickHandle" href="http://baidu.com">百度</a>
<div @click="clickDiv">
<p @click="clickP">测试冒泡</p>
</div>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
clickHandle(e) {
e.preventDefault()
console.log('点击了')
},
clickDiv() {
console.log("DIV")
},
clickP(e) {
e.stopPropagation()
console.log("P")
}
}
}
</script>
数组变化侦听
变更方法
<template>
<h3>数组变化侦听</h3>
<button @click="addListHandle">添加数据</button>
<ul>
<li v-for="(item,index) of names" :key="index">{{ item }}</li>
</ul>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "ime", "frank"]
}
},
methods: {
addListHandle() {
// 引起UI的变化
this.names.push("HaHa")
// 不会引起UI自动更新
this.names.concat(["HaHa"])
}
}
}
</script>
替换方法
想发生变化的话:
this.name = this.name.concat(["HaHa"])
<template>
<h3>数组变化侦听</h3>
<button @click="addListHandle">添加数据</button>
<ul>
<li v-for="(item,index) of names" :key="index">{{ item }}</li>
</ul>
<button @click="filterHandele">合并数据</button>
<h3>数组1</h3>
<p v-for="(item, index) of nums1" :key="index">{{ item }}</p>
<h3>数组2</h3>
<p v-for="(item, index) of nums2" :key="index">{{ item }}</p>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "ime", "frank"],
nums1:[1, 2, 3, 4, 5],
nums2:[6, 7, 8, 9, 10],
}
},
methods: {
addListHandle() {
// 引起UI的变化
this.names.push("HaHa")
// 不会引起UI自动更新
this.names.concat(["HaHa"])
},
filterHandele() {
this.nums1 = this.nums1.concat(this.nums2)
},
}
}
</script>
计算属性
<template>
<h3>数组变化侦听</h3>
<button @click="addListHandle">添加数据</button>
<ul>
<li v-for="(item,index) of names" :key="index">{{ item }}</li>
</ul>
<button @click="filterHandele">合并数据</button>
<h3>数组1</h3>
<p v-for="(item, index) of nums1" :key="index">{{ item }}</p>
<h3>数组2</h3>
<p v-for="(item, index) of nums2" :key="index">{{ item }}</p>
</template>
<script>
export default {
data() {
return {
names:["XiaoMo", "ime", "frank"],
nums1:[1, 2, 3, 4, 5],
nums2:[6, 7, 8, 9, 10],
}
},
methods: {
addListHandle() {
// 引起UI的变化
this.names.push("HaHa")
// 不会引起UI自动更新
this.names.concat(["HaHa"])
},
filterHandele() {
this.nums1 = this.nums1.concat(this.nums2)
},
}
}
</script>
计算属性和函数的区别
计算属性的值会基于其响应式依赖被缓存,一个计算属性的值仅在其响应式依赖更新时再重新计算。
函数则每次都会重新调用并计算。
Class 绑定
<template>
<p :class="{'active': isActive, 'text-danger': hasError}"> Class样式绑定</p>
</template>
<script>
export default {
data() {
return {
isActive: true,
hasError: true,
}
},
}
</script>
<style>
.active {
font-size: 30px;
}
.text-danger {
color: red;
}
</style>
多个对象的绑定形式
<template>
<p :class="{'active': isActive, 'text-danger': hasError}"> Class样式绑定1</p>
<p :class="classObject"> Class样式绑定2</p>
</template>
<script>
export default {
data() {
return {
isActive: true,
hasError: true,
classObject: {
'active': false,
'text-danger': true,
}
}
},
}
</script>
<style>
.active {
font-size: 30px;
}
.text-danger {
color: red;
}
</style>
绑定数组
<template>
<p :class="{'active': isActive, 'text-danger': hasError}"> Class样式绑定1</p>
<p :class="classObject"> Class样式绑定2</p>
<p :class="[arrActive, arrHasError]"> Class样式绑定3</p>
</template>
<script>
export default {
data() {
return {
isActive: true,
hasError: true,
classObject: {
'active': false,
'text-danger': true,
},
arrActive: "active",
arrHasError: "text-danger",
}
},
}
</script>
<style>
.active {
font-size: 30px;
}
.text-danger {
color: red;
}
</style>
数组和对象
必须是数组嵌套对象,不能是对象嵌套数组。
Style 绑定
<template>
<p :style="{color: activeColor, fontSize: fontSize + 'px'}">Style 绑定1</p>
<p :style=stytleObject>Style 绑定2</p>
</template>
<script>
export default {
data() {
return {
activeColor: 'red',
fontSize: 30,
stytleObject: {
color: "red",
fontSize: "30px",
},
}
},
}
</script>
侦听器
只能监听响应式的数据。
<template>
<h3>侦听器</h3>
<p>{{ message }}</p>
<button @click="updatHandle"> 修改数据 </button>
</template>
<script>
export default {
data() {
return {
message: "Hello",
}
},
methods: {
updatHandle() {
this.message = "World!"
}
},
// 侦听器
watch: {
// newValue改变之后的数据
// oldValue改变之后的数据
// 函数名必须与侦听的数据对象保持一致
message(newValue, oldValue) {
// 数据发生变化,自动执行的函数
console.log(oldValue);
console.log(newValue);
}
}
}
</script>
表单输入绑定
v-model
实时获取:
<template>
<h3>表单输入绑定</h3>
<form>
<input type="text" v-model="message">
<p>{{ message }}</p>
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
</form>
</template>
<script>
export default {
data() {
return {
message: "",
checked: false,
}
}
}
</script>
非实时获取(失去焦点后获取)
<template>
<h3>表单输入绑定</h3>
<form>
<input type="text" v-model.lazy="message">
<p>{{ message }}</p>
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
</form>
</template>
<script>
export default {
data() {
return {
message: "",
checked: false,
}
}
}
</script>
模板引用
获取dom
内容改变: {{ 模板语法 }}
属性改变: v-bind: 指令
事件:v-on:click
如果没有特别的需求,不要操作DOM
<template>
<div ref="container" class="container">{{ content }}</div>
<input type="text" ref="username">
<button @click="getElementHandle">获取元素</button>
</template>
<script>
export default {
data() {
return {
content: "内容",
}
},
methods: {
getElementHandle() {
this.$refs.container.innerHTML="HaHaHa";
console.log(this.$refs.username.value);
}
}
}
</script>
组件组成
我们一般会将Vue组件定义再一个单独的 .vue 文件中。
<template>
<div class="container">{{ message }}</div>
</template>
<script>
export default {
data() {
return {
message: "组建的基本组成"
}
}
}
</script>
<style>
.container {
font-size: 30px;
color: red;
}
</style>
引用方法
<template>
<!-- 2.显示组件 -->
<MyComponent />
</template>
<script setup>
// 1.引入组件
import MyComponent from './components/MyComponent.vue';
</script>
<style></style>
组件嵌套关系
App.vue
<template>
<Headers/>
<Mains/>
<Asides/>
</template>
<script setup>
import Headers from "./pages/Headers.vue"
import Mains from "./pages/Mains.vue";
import Asides from "./pages/Asides.vue";
</script>
<style>
</style>
Articles.vue
<template>
<h3>Article</h3>
</template>
<style scoped>
h3 {
width: 80%;
margin: 0 auto;
text-align: center;
line-height: 100px;
box-sizing: border-box;
margin-top: 50px;
background: #999;
}
</style>
Asides.vue
<template>
<div class="aside">
<h3>Aside</h3>
<item/>
<item/>
<item/>
</div>
</template>
<script setup>
import item from './item.vue';
</script>
<style scoped>
.aside {
float: right;
width: 30%;
height: 600px;
border: 5px solid #999;
box-sizing: border-box;
}
</style>
Mains.vue
<template>
<div class="main">
<h3>Main</h3>
<Articles/>
<Articles/>
</div>
</template>
<script setup>
import Articles from './Articles.vue';
</script>
<style scoped>
.main {
float: left;
width: 70%;
height: 600px;
border: 5px solid #999;
box-sizing: border-box;
}
</style>
Headers.vue
<template>
<h3>Header</h3>
</template>
<style scoped>
h3 {
width: 100%;
height: 100px;
border: 5px solid #999;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
</style>
Item.vue
<template>
<h3>Item</h3>
</template>
<style scoped>
h3 {
width: 80%;
margin: 0 auto;
text-align: center;
line-height: 100px;
box-sizing: border-box;
margin-top: 10px;
background: #999;
}
</style>
组件的注册方式
全局注册
import { createApp } from 'vue'
import App from './App.vue'
import Headers from "./pages/Headers.vue"
const app = createApp(App)
// 在这中间写组件的注册
app.component("Headers", Headers)
app.mount('#app')
局部注册
...见上节
组件传递数据
props
parent.vue
<template>
<h3>Parent</h3>
<Child title="Parent数据" demo = "测试"/>
</template>
<script>
import Child from "./Child.vue"
export default {
data() {
return {
}
},
components: {
Child
},
}
</script>
Child.vue
<template>
<h3>Child</h3>
<p>{{ title }}</p>
<p>{{ demo }}</p>
</template>
<script>
export default {
data() {
return {
}
},
props:["title", "demo"]
}
</script>
动态数据传递
parent.vue
<template>
<h3>Parent</h3>
<Child :title="message"/>
</template>
<script>
import Child from "./Child.vue"
export default {
data() {
return {
message: "动态数据"
}
},
components: {
Child
},
}
</script>
注意事项:
props 传递数据只能从父级传递给子级,不能反其道而行。
组件传递多种数据类型
<template>
<h3>Parent</h3>
<Child :title="message" :age="age"/>
</template>
<script>
import Child from "./Child.vue"
export default {
data() {
return {
message: "动态数据",
age: 20,
}
},
components: {
Child
},
}
</script>
组件传递 Props 效验
Props 是只读的,不可修改。
<template>
<h3>Component B</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<p v-for="(item, index) of names" :key="index">{{ item }}</p>
</template>
<script>
export default {
data() {
return {
}
},
props:{
title:{
type: [String, Number],
// 设置必选项
required: true,
},
age: {
type: Number,
default: 0,
},
// 数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
names: {
type: Array,
default() {
return ["HaHa", "QwQ"]
}
}
}
}
</script>
组件事件
$emit 方法触发自定义事件,实现子传父数据。
Child.vue
<template>
<h3>Child</h3>
<button @click="clickEventHandle">传递数据</button>
</template>
<script>
export default {
data() {
return {
msg: "Child数据!",
}
},
methods: {
clickEventHandle() {
// 自定义事件
this.$emit("someEvent", "Child数据")
}
}
}
</script>
Event.vue
<template>
<h3>组件事件</h3>
<Child @someEvent="getHandle"/>
<p>父元素:{{ message }}</p>
</template>
<script>
import Child from "./Child.vue"
export default {
data() {
return {
message:""
}
},
components: {
Child,
},
methods: {
getHandle(data) {
console.log("触发了", data);
this.message = data;
}
}
}
</script>
组件事件配合 v-model 使用
Mains.vue
<template>
<h3>Main</h3>
<p>搜索的内容为:{{ search }}</p>
<Search @searchEvent="getSearch"/>
</template>
<script>
import Search from './Search.vue';
export default{
data() {
return {
search:""
}
},
components: {
Search,
},
methods: {
getSearch(data) {
this.search = data;
}
}
}
</script>
Search.vue
<template>
搜索:<input type="text" v-model="search">
</template>
<script>
export default {
data() {
return {
search: ""
}
},
watch: {
search(newValue, oldeValue) {
this.$emit("searchEvent", newValue);
}
}
}
</script>
组合数据传递
通过 props 实现子传父
AAA.vue
<template>
<h3>AAA</h3>
<p>{{ message }}</p>
<BBB title="标题" :onEvent="dataFn"/>
</template>
<script>
import BBB from './BBB.vue';
export default {
data() {
return {
message: ""
}
},
components: {
BBB,
},
methods: {
dataFn(data) {
this.message = data
}
}
}
</script>
BBB.vue
<template>
<h3>BBB</h3>
<p>{{ title }}</p>
<p>{{ onEvent("传递数据") }}</p>
</template>
<script>
export default {
data() {
return {
}
},
props: {
title: String,
onEvent: Function,
}
}
</script>
插槽Slots
传递HTML结构
slot 元素是插槽的一个出口,标志了渲染的位置。
App.vue
<template>
<SlotsBase>
<div>
<h3>插槽标题</h3>
<p>插槽内容</p>
</div>
</SlotsBase>
</template>
<script>
import SlotsBase from './components/SlotsBase.vue';
export default {
components: {
SlotsBase,
}
}
</script>
<style>
</style>
SlotsBase.vue
<template>
<slot></slot>
<h3>插槽基础知识</h3>
</template>
<script>
</script>
渲染作用域
插槽内容可以访问到父组件的数据作用域。
App.vue
<template>
<!-- <SlotsBase>
<div>
<h3>插槽标题</h3>
<p>插槽内容</p>
</div>
</SlotsBase> -->
<SlotsTwo>
<h3>{{ message }}</h3>
</SlotsTwo>
</template>
<script>
import SlotsBase from './components/SlotsBase.vue';
import SlotsTwo from './components/SlotsTwo.vue';
export default {
data() {
return {
"message": "插槽内容续集",
}
},
components: {
SlotsBase,
SlotsTwo,
}
}
</script>
<style>
</style>
SlotsTwo.vue
<template>
<h3>Slots续集</h3>
<slot></slot>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
默认内容
如果插槽内无传递,那么可以在插槽中自己写默认内容。
具名插槽
可以通过名字来实现多个插槽不同渲染。
App.vue
<template>
<!-- <SlotsBase>
<div>
<h3>插槽标题</h3>
<p>插槽内容</p>
</div>
</SlotsBase> -->
<SlotsTwo>
<template v-slot:header>
<h3>{{ message }}</h3>
</template>
<template v-slot:main>
<h3>{{ message }}</h3>
</template>
</SlotsTwo>
</template>
<script>
import SlotsBase from './components/SlotsBase.vue';
import SlotsTwo from './components/SlotsTwo.vue';
export default {
data() {
return {
"message": "插槽内容续集",
}
},
components: {
SlotsBase,
SlotsTwo,
}
}
</script>
<style>
</style>
SlotsTwo.vue
<template>
<h3>Slots续集</h3>
<slot name="header"></slot>
<hr>
<slot name="main"></slot>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
v-slot: 可以用 # 简写。
slots同时使用父元素和子元素
App.vue
<template>
<!-- <SlotsBase>
<div>
<h3>插槽标题</h3>
<p>插槽内容</p>
</div>
</SlotsBase> -->
<!-- <SlotsTwo>
<template #header>
<h3>{{ message }}</h3>
</template>
<template #main>
<h3>{{ message }}</h3>
</template>
</SlotsTwo> -->
<SlotsAttr v-slot="slotProps">
<h3>{{ Test }} - {{ slotProps.msg }}</h3>
</SlotsAttr>
</template>
<script>
import SlotsBase from './components/SlotsBase.vue';
import SlotsTwo from './components/SlotsTwo.vue';
import SlotsAttr from './components/SlotsAttr.vue';
export default {
data() {
return {
"message": "插槽内容续集",
"Test": "测试内容",
}
},
components: {
SlotsBase,
SlotsTwo,
SlotsAttr,
}
}
</script>
<style>
</style>
SlotsAttr.vue
<template>
<h3>Slots再续集</h3>
<slot :msg="childMessage"></slot>
</template>
<script>
export default {
data() {
return {
childMessage: "子组件信息",
}
},
}
</script>
具名插槽实现子父组件相互交互
App.vue
<template>
<!-- <SlotsBase>
<div>
<h3>插槽标题</h3>
<p>插槽内容</p>
</div>
</SlotsBase> -->
<!-- <SlotsTwo>
<template #header>
<h3>{{ message }}</h3>
</template>
<template #main>
<h3>{{ message }}</h3>
</template>
</SlotsTwo> -->
<SlotsAttr>
<template #header="slotProps">
<h3>{{ Test }} - {{ slotProps.msg }}</h3>
</template>
<template #main="slotProps">
<p>{{ slotProps.job }}</p>
</template>
</SlotsAttr>
</template>
<script>
import SlotsBase from './components/SlotsBase.vue';
import SlotsTwo from './components/SlotsTwo.vue';
import SlotsAttr from './components/SlotsAttr.vue';
export default {
data() {
return {
"message": "插槽内容续集",
"Test": "测试内容",
}
},
components: {
SlotsBase,
SlotsTwo,
SlotsAttr,
}
}
</script>
<style>
</style>
SlotsAtte.vue
<template>
<h3>Slots再续集</h3>
<slot name="header" :msg="childMessage"></slot>
<slot name="main" :job="jobmessage"></slot>
</template>
<script>
export default {
data() {
return {
childMessage: "子组件信息",
jobmessage: "XiaoMo",
}
},
}
</script>
组件生命周期
App.vue
<template>
<h3>组件的生命周期</h3>
<p>{{ message }}</p>
<button @click="updateHandle"> 更新数据 </button>
</template>
<script>
/**
* 生命周期函数
* 创建期: beforeCreate created
* 挂载期: beforeMount mounted
* 更新期: beforeUpdate updated
* 销毁期: beforeUnmount unmounted
*/
export default {
data() {
return {
message: "更新之前",
}
},
methods: {
updateHandle() {
this.message = "更新之后";
}
},
beforeCreate() {
console.log("组件创建之前");
},
created() {
console.log("组件创建之后");
},
beforeMount() {
console.log("组件渲染之前");
},
mounted() {
console.log("组件渲染之后");
},
beforeUpdate() {
console.log("组件更新之前");
},
updated() {
console.log("组件更新之后");
},
beforeUnmount() {
console.log("组件销毁之前");
},
unmounted() {
console.log("组件销毁之后");
},
}
</script>
生命周期应用
通过 ref 读取元素
<template>
<h3>组件生命周期函数应用</h3>
<p ref="name">XiaoMo</p>
</template>
<script>
export default {
beforeMount() {
console.log(this.$refs.name); // undefined
},
mounted() {
console.log(this.$refs.name); // ok
}
}
</script>
模拟网络请求:
<template>
<h3>组件生命周期函数应用</h3>
<p ref="name">XiaoMo</p>
<ul>
<li v-for="(item, index) of banner" :key="index">
<h3>{{ item.title }}</h3>
<p>{{ item.content }}</p>
</li>
</ul>
</template>
<script>
export default {
data() {
return {
banner: [],
}
},
beforeMount() {
console.log(this.$refs.name); // undefined
},
mounted() {
// 模拟网络请求
this.banner = [
{
"title": "HaHa",
"content": "QwQ",
},
{
"title": "XiaoMo",
"content": "QwQ",
},
]
console.log(this.$refs.name); // ok
},
}
</script>
动态组件
<template>
<!-- <UseDemo/> -->
<component :is="tabComponent"></component>
<button @click="changeHandle">切换组件</button>
</template>
<script>
import UseDemo from './components/UseDemo.vue';
import AAA from './components/AAA.vue';
import BBB from './components/BBB.vue';
export default {
data() {
return {
tabComponent: "AAA",
}
},
components: {
UseDemo,
AAA,
BBB,
},
methods: {
changeHandle() {
this.tabComponent = this.tabComponent == "AAA" ? "BBB" : "AAA";
}
}
}
</script>
组件保持存活
让组件不被卸载。
<keep-alive>
<component :is="tabComponent"></component>
</keep-alive>
<template>
<!-- <UseDemo/> -->
<keep-alive>
<component :is="tabComponent"></component>
</keep-alive>
<button @click="changeHandle">切换组件</button>
</template>
<script>
import UseDemo from './components/UseDemo.vue';
import AAA from './components/AAA.vue';
import BBB from './components/BBB.vue';
export default {
data() {
return {
tabComponent: "AAA",
}
},
components: {
UseDemo,
AAA,
BBB,
},
methods: {
changeHandle() {
this.tabComponent = this.tabComponent == "AAA" ? "BBB" : "AAA";
}
}
}
</script>
异步组件
<template>
<!-- <UseDemo/> -->
<keep-alive>
<component :is="tabComponent"></component>
</keep-alive>
<button @click="changeHandle">切换组件</button>
</template>
<script>
import { defineAsyncComponent } from 'vue'
import UseDemo from './components/UseDemo.vue';
import AAA from './components/AAA.vue';
// import BBB from './components/BBB.vue';
const BBB = defineAsyncComponent(() =>
import("./components/BBB.vue")
)
export default {
data() {
return {
tabComponent: "AAA",
}
},
components: {
UseDemo,
AAA,
BBB,
},
methods: {
changeHandle() {
this.tabComponent = this.tabComponent == "AAA" ? "BBB" : "AAA";
}
}
}
</script>
依赖注入
props逐级透传
App.vue
<template>
<h3> 祖先 </h3>
<Parent />
</template>
<script>
import Parent from "./components/Parent.vue"
export default {
provide: {
message: "祖先的财产",
},
components: {
Parent
},
}
</script>
Child.vue
<template>
<h3> Child </h3>
<p>{{ message }}</p>
</template>
<script>
export default {
inject:["message"]
}
</script>
必须要存在依赖关系才可以使用 provide 和 inject 传递数据。
全局注入
// import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.provide("golabData", "全局数据")
app.mount('#app')
Vue 应用
import { createApp } from 'vue'
import App from './App.vue'
// app: Vue 的实例对象
// 在一个 Vue 项目中,有且只有一个 Vue 实例对象
const app = createApp(App)
// App:根组件
app.provide("golabData", "全局数据")
// 挂载到容器中
app.mount('#app')
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<!--
浏览器可执行文件:
1.HTML
2.CSS
3.JS
4.Image
构建工具:Webpack vite
-->
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

浙公网安备 33010602011771号