学习资料
前提条件:
熟悉命令行
前端标配三件套(HTML,JavaScript,CSS,)
已安装15.0或更高版本的Node.js(点击跳转下载Node.js)
学习笔记
使用命令行创建Vue项目
创建Vue项目:
npm init vue@latest
使用vite快速构建vue3+ts项目: npm create vite@latest 《项目名称》 --template ts
按提示配置初始化项目
运行项目:
cd到项目:
cd my_vue_project
安装:
npm install
运行:
npm run dev
模板语法
Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。
VUE项目是从哪开始运行的
每个 Vue 应用都是通过main.js
文件中createApp
函数创建一个新的 应用实例
import { createApp } from 'vue'
//引入跟组件
import App from './App.vue'
//创建根组件
const app=createApp(App);
//挂载根组件
//挂载到index.html文件内 id='app'的view上
app.mount('#app');
公共资源路径 src/assets
<script>
结构体-选项式
<script>
import name from "@/组件路径";// 导入组件
export default {
// 注入组件
components:{name},
//存放变量
data(){return{/*key:value*/}},
//存放方法
methods:{},
//计算属性
computed:{},
//监听变量变化
watch:{},
//接收标签传值
props:{},
//向下组件树注入依赖数据
provide:{},
//向上组件树引用依赖数据
inject:{},
//生命周期:
beforeCreate() {},//创建前
created(){},//创建后
beforeMount() {},//挂载前
mounted() {},//挂载后
beforeUpdate() {},//更新前
updated() {},//更新后
beforeUnmount() {},//卸载前
unmounted() {},//卸载后
errorCaptured(){}//异常捕捉
}
</script>
文本插值
使用{{ value }}
引用变量,可执行运算
<template>
<a>我是{{ name }}</a>
<a>我的爱好是:{{ method() }}</a>
</template>
<script>
export default {
components: {HelloWorld},
data() {
return {
name: "张三",
method: function () {
return "写代码"
}
}
}
}
</script>
效果:
插入HTML
使用v-html
属性插入原始Html
v-html="value变量 或 html代码"
<template>
<p>显示纯文本:{{ rawHtml }}</p>
<p>镶入Html:<span v-html="rawHtml"></span></p>
</template>
<script>
export default {
data() {
return {
rawHtml: "<a href='http://bbs.jie-you.cn'>解忧社区</a>"
}
}
}
</script>
效果:
属性绑定
使用
v-bind:
绑定/设置标签属性(可使用":"简写)
<template>
<a v-bind:href="url">点击跳转</a>
<a :href="url">点击跳转</a>
</template>
<script>
export default {
data() {
return {
url: "http://blog.jie-you.cn",
}
}
}
</script>
使用
v-bind="object"
引用整个对象作为标签属性
<template>
<a v-bind="object">引用整个对象object作为标签a的属性</a>
</template>
<script>
export default {
data() {
return {
object: {
id: "test",
class: "redClass",
href: "http://blog.jie-you.cn",
other:"自定义属性"
}
}
}
}
</script>
<style>
.redClass {
color: #ff0000;
}
.blueClass {
color: #00a6ff;
}
</style>
条件渲染
v-if="flag"
如果flag条件为true则渲染所在标签控件v-else-if="flag"
或者flag条件为true则渲染所在标签控件v-else
否则渲染所在标签控件v-show="flag"
如果flag条件为true则渲染并显示所在标签控件,否则渲染但不显示所在标签控件
v-if
:切换时性能开销大,初始渲染时性能开销小
v-show
:切换时性能开销小,初始渲染时性能开销打
通过Key管理状态
通过v-bind
绑定key赋于唯一值
未绑定key时数据变化会重新渲染全部列表,造成性能开销
<template>
<p v-for="(item,index) of array" :key="item.id">{{ item.value }}</p>
</template>
<script>
export default {
data() {
return {
array: [{
id: 10001,
value: "A"
}, {
id: 10002,
value: "B"
}, {
id: 10003,
value: "C"
}]
}
}
}
</script>
事件处理
通过使用 v-on:
(简写"@") 来监听DOM事件,并在事件触发时执行对应的JavaScript。用法:
on:click="函数/JS/表达式"
或 @click="函数/JS/表达式"
练手示例:
<template>
<h3>事件处理</h3>
<button v-on:click="logData('当前Index的值为'+index)"> 输出日志</button>
<p>index:{{ index }}
<button @click="index++"> +1</button>
<button @click="indexAdd5()"> +5</button>
</p>
</template>
<script>
export default {
data() {
return {
index: 0,
logData: function (data) {
console.log(this.index);
console.log(data);
}
}
},
methods: {
indexAdd5() {
this.index += 5;
this.logData("当前Index的值为" + this.index);
}
}
}
</script>
事件修饰符
.stop
阻止事件冒泡-拦停事件使父组件事件不被触发
.prevent
阻止默认事件-使默认事件不被触发
.once
触发一次事件
.enter
回车键触发
事件修饰符示例:
<template>
<h3>Event事件绑定</h3>
<button v-on:click="print($event,'233')">点击打印</button>
<p>
<a v-on:click="(e)=>{console.log('阻止了点击事件');e.preventDefault()}" href="http://blog.jie-you.cn">阻止跳转网址(e.preventDefault())</a>
</p>
<p>
<a @click.prevent="(e)=>{console.log(e);}" href="http://blog.jie-you.cn">阻止跳转网址(.prevent)</a>
</p>
<div @click=" ()=>{console.log('<div>标签 点击事件触发了')}">
<p @click.stop=" (e)=>{console.log('<p>标签 点击事件触发了');e.stopPropagation()}">阻止冒泡(e.stopPropagation())</p>
</div>
<div @click=" ()=>{console.log('<div>标签 点击事件触发了')}">
<p @click.stop=" ()=>{console.log('<p>标签 点击事件触发了')}">阻止冒泡(.stop)</p>
</div>
</template>
<script>
export default {
data() {
return {}
},
methods: {
print(v, e) {
console.log(v)
console.log(e)
}
}
}
</script>
常用事件列表
展开/收起
鼠标事件
- click:用户点击元素。
- dblclick:用户双击元素。
- mouseover:鼠标移到元素上方。
- mouseout:鼠标从元素移开。
- mousedown:用户按下鼠标按钮。
- mouseup:用户释放鼠标按钮。
- mousemove:鼠标在元素内移动。
键盘事件
- keydown:用户按下键盘键。
- keyup:用户释放键盘键。
- keypress:字符键在完全按下后触发。
表单事件
- submit:提交表单。
- change:元素值改变。
- input:输入框的值被修改。
- focus:元素获得焦点。
- blur:元素失去焦点。
触摸事件
- touchstart:触摸点放在触摸表面上。
- touchmove:触摸点在触摸表面上移动。
- touchend:触摸点从触摸表面上移开。
- touchcancel:系统取消触摸。
窗口事件
- resize:浏览器窗口大小改变。
- scroll:滚动观察的元素。
资源事件
- load:页面完成加载。
- unload:用户退出页面。
- error:加载时发生错误。
其他事件
- contextmenu:用户点击鼠标右键打开上下文菜单。
数组变化监听
过简,略....
常用数组操作方法
改变原数组:
1. push()
末尾添加数据
2. pop()
末尾出删除数据
3.unshift()
头部添加数据
4.shift()
头部删除数据
5.reverse()
翻转数组
6.sort()
排序
7.splice()
截取数组
不改变原数组
1.concat()
合并数组
2.join()
数组转字符串
3.slice()
截取数组的一部分数据
4.indexOf()
从左检查数组中有没有这个数值
5.lastIndexOf()
从右检查数组中有没有这个数值
ES6新增的数组方法
1. forEach()
用来循环遍历的 for
2.map()
映射数组的
3.filter()
过滤数组
4.every()
判断数组是不是满足所有条件
5.some()
数组中有没有满足条件的
6.find()
用来获取数组中满足条件的第一个数据
7.reduce()
叠加后的效果
计算属性
计算属性值会基于其响应式依赖被缓存。
一个计算属性仅会在其响应式依赖更新时才重新计算,而方法调用总是会在重渲染发生时再次执行函数
关键字:computed:{方法},
<template>
<p v-for="(v,i) of data.array">{{ v }}
<button @click="arrayRemove(i)">删除</button>
</p>
<button @click="arrayAdd(data.array.length+1)">添加</button>
<p>{{ data.array.length <= 0 ? "表达式->数组为空" : "表达式->数组不为空" }}</p>
<p>{{ methods_isEmpty() }}</p>
<p>{{ computed_isEmpty }}</p>
</template>
<script>
export default {
//变量数据存放
data() {
return {
data: {
array: ['1', '2', '3', '4', '5', '6']
}
}
},
//方法函数存放
methods: {
methods_isEmpty() {
return this.data.array.length <= 0 ? "方法->数组为空" : "方法->数组不为空"
},
arrayAdd(v) {
this.data.array.push(`new${v}`);
},
arrayRemove(i) {
this.data.array.splice(i, 1)
}
},
//计算属性存放
computed: {
computed_isEmpty() {
return this.data.array.length <= 0 ? "计算->数组为空" : "计算->数组不为空"
}
}
}
</script>
Class绑定
数据绑定的一个常见需求场景是操纵元素的 Css class 列表,因为 class 是 attribute,我们可以和其他attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 class的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组
绑定对象示例(含单对象表达,单对象引用,单数组引用,动态计算引用):
<template>
<p :class="{'class1':theClassObj.class1}">绑定单个样式</p>
<p :class="theClassObj">绑定整个对象</p>
<p :class="theClassArray">绑定一个数组</p>
<p :class="getUserClassArray">运算+绑定一个数组</p>
<p :class="getUserClassObject">运算+绑定一个对象</p>
</template>
<script>
export default {
data() {
return {
theClassObj: {
'class1': true,
'class2': false,
'class3': true,
},
theClassArray: ['class1', 'class2'],
}
},
computed: {
getUserClassArray() {
return [
this.theClassObj.class1 ? 'class1' : '',
this.theClassObj.class2 ? 'class2' : '',
this.theClassObj.class3 ? 'class3' : ''
]
},
getUserClassObject() {
const c1 = this.theClassObj.class1;
const c3 = this.theClassObj.class3;
return {
'class1': c1,
'class2': c1 && c3,//c1,c3为true 设定使用class2
'class3': c3,
}
}
}
}
</script>
<style>
.class1 {
color: red;
}
.class2 {
color: #0095ff;
font-size: 15px;
}
.class3 {
color: #3d3407;
font-size: 30px;
}
</style>
效果:
进阶:数组/对象混合嵌套(仅允许数组内镶嵌对象)
<p :class="['class1',{'class2':theClassObj.class2},'class3']">数组内镶嵌对象</p>
<!--举一反三 故略...-->
Style绑定
同Class绑定大同小异 故略...
<p :style="{color:'red',fontSize:(()=>{return 50})() +'px'}"> style绑定 </p><!--对象表达式-->
<p :style="Object1">style绑定</p><!--引用对象-->
<p :style="[Object1,Object2]">style绑定</p><!--数组镶对象-不推荐-->
侦听器
关键字:watch:{方法}
,方法名称设置为要监听的变量key的值
<template>
<p>value:{{ value }}</p>
<button @click="value+=1">加1</button>
<p>object:{{ object }}</p>
<button @click="add_v_k1">object.k1加1</button>
<button @click="object=Object.assign({newK:0},object)">object赋值</button>
</template>
<script>
export default {
data() {
return {
value: 0,
object: {
k1: 0,
k2: 0
}
}
},
methods: {
//修改指定数据的方法
add_v_k1() {
const o_v = this.object.k1;
this.object.k1 += 1;
const n_v = this.object.k1;
this.watch_v_k1(n_v, o_v);//调用自定义侦听器
},
//自定义侦听器
watch_v_k1(n_v, o_v) {
console.log(`自定义侦听器 => 监听到value2中的k1被修改:${o_v} => ${n_v}`);
}
},
//watch侦听器-方法名必须等于需要监听的变量key名称
watch: {
value(newValue, oldValue) {
console.log(`watch侦听器 =>监听到value的值被修改:${oldValue} => ${newValue}`);
},
object(n_v, o_v) {
console.log(`watch侦听器 =>监听到object被重新赋值:${JSON.stringify(o_v)} => ${JSON.stringify(n_v)}`);
},
}
}
</script>
表单输入绑定
使用v-model
连接绑定
<template>
<h3>表单连接与绑定</h3>
<input :type="'text'" v-model="modelValue1">
<button @click="delAll"> 清空输入框</button>
<button @click="()=>{add('hello')}"> 插入数据"hello"</button>
<br><br>
<input :type="'checkbox'" :id="'checkbox'" v-model="checked">
<label for="checkbox">勾选状态: {{ checked }} </label>
</template>
<script>
export default {
data() {
return {
modelValue1: "hello world",
checked: false,
}
},
methods: {
delAll() {
this.modelValue1 = "";
},
add(v) {
this.modelValue1 += v;
}
},
watch: {
modelValue1(n, o) {
console.log(`监听到输入内容变化"${n}"=>"${o}"`);
},
checked(n, o) {
console.log(`监听到勾选状态变化"${n}"=>"${o}"`);
}
}
}
</script>
修饰符:
.number
只接收输入的数字
.trim
过滤首尾空格符
.lazy
懒获取-回车/失去焦点..等change事件时响应
模板引用-操作DOM
获取操作DOM:
使用
ref="标识值"
属性给定一个标识值使用
this.$refs.标识值
可以获取该DOM
赋值:ref="container"
获取DOM:
例1:this.$refs.container
例2:this.$refs.container.value
修改DOM:
例1:this.$refs.container.innerHTML='Html'
例2:this.$refs.container.value='value'
注意:如果没有特别需求不要操作DOM,耗性能
示例:
<template>
<div class="container" ref="container"> 视图容器-{{ content }}</div>
<button @click="getElementHandle">获取元素</button>
<button @click="setView">改变元素</button>
<button @click="reView">重置元素</button>
<br><br>
<input type="text" ref="theInput">
<button @click="getInput">获取元素</button>
</template>
<script>
/**
* 内容改变:{{内容}}
* 属性改变: v-bind:属性="" 简写(:class="")
* 事件:v-on:click="" 简写(@click="")
* 获取DOM: 使用ref属性给定一个标识值,使用"this.$refs.标识值"可以获取该DOM
* 赋值:(ref="container")
* 获取:(this.$refs.container) / (this.$refs.container.value)
* 修改:(this.$refs.container.innerHTML='Html')
* (this.$refs.container.value='value')
* 注意:如果没有特别需求不要操作DOM,耗性能
*/
export default {
data() {
return {
content: "内容",
}
},
methods: {
getElementHandle() {
console.log(this.$refs.container);
},
getInput() {
console.log(this.$refs.theInput.value);
},
setView() {
this.$refs.container.innerHTML = '<h3>我是新DOM视图</h3>';
},
reView() {
this.$refs.container.innerHTML = `视图容器-${this.content}`;
}
}
}
</script>
组件组成
组件最大的优势就是可复用性
当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的.vue
文件中,这被叫做单文件组件(简称 SFC)
创建一个自定义组件
<!--View视图区 必须-->
<template>
<div class="theClass">View视图部分</div>
</template>
<!--方法逻辑区 可选-->
<script>
export default {
data() {
return {}
}
}
</script>
<!--CSS样式区 可选-->
<style>
.theClass {
color: red;
font-size: 30px;
}
</style>
引用自定义组件
一:<script>
内引入组件:
import 赋予名称 from "@组件路径"
二:<script>
=>export default
=>components
对象内注入组件:
components:{赋予名称}
三:<template>
内使用组件<组件名/>
<template>
<myModel/> <!--写法(赋予名称)-->
<my-model/><!--写法2(赋予-名称)-->
</template>
完整引用示例:
<script>
// 一,引入组件: import 赋予名称 from "@组件路径"
import myModel from "@/components/TheModule.vue"
export default {
//二,注入组件: 在components对象内声明注入
components:{
myModel
}
}
</script>
<template>
<!--第三部:使用组件 <组件名/> -->
<myModel/> <!--写法1-->
<my-model/><!--写法2-->
</template>
<style>
</style>
全局组件注册
在main.js
文件中操作注入全局组件:
1,通过import 组件名称 from “@组件路径”
导入组件
2,将默认createApp(App).mount('#app')
拆分开
3,在中间注入组件:.component("赋予名称",组件名称)
import { createApp } from 'vue'
import App from './App.vue'
//引入组件
import TheModule from "@/components/TheModule.vue";
// createApp(App).mount('#app') 拆分开 再中间插入挂载组件
const app=createApp(App);
app.component("TheModel",TheModule);//注入
app.mount('#app');
style标签-关键字:scoped
使用scoped关键字后,当前style样式只在当前组件内生效 为定义scoped则全局有效
组件嵌套关系
Root
-Header
-Main
--Article1
--Article2
--...
-Aside
--Item1
--Item2
--...
组件传递数据
略...总结:
子组件通过props:['data1','data2']
接受传入的值
1,在引入的子组件标签中插入自定义属性并赋值<item data1="hello"/>
2,在子组件中通过props:["属性1","属性2"]
接收
*传递复杂数据使用v-bind:绑定
传递数据的类型校验与默认值
//示例1 -校验接收String类型
props: {
name: {
type: String,
}
}
//示例2 -要求必须传值
props: {
name: {
type: String,
//要求必须传递值,否则打印警告
required:true
}
}
//示例3 -校验接收多个类型,设置默认值
props: {
data: {
type: [String, Number,
default: "默认数据值"
}
}
//示例4 -数组和对象类型的传递默认值,需使用工厂函数返回默认值
props: {
arrList: {
type: Array,
default() {
return ["默认1", "默认2", "默认3"];
}
}
}
注意:
props
接收到的值不允许被修改可传入回调函数实现通信...略
组件事件
在组件的模板表达式中,可以直接使用 $emit
方法触发自定义事件
触发自定义事件的目的是组件之间传递数据
触发-发送事件:
通过this.$emit("Event名称","传值Value")
发送事件
监听-接收事件:
组件通过 @Event名称="调用方法"
绑定事件,当事件触发时便可接收到
总结
组件之间传递数据的方案:
父传子 - props:{job}
-传入回调函数可实现通信
子传父 - this.$emit("e_name","value")
举一反三
v-model
+watch
联动组件事件
,即可实现跨组件之间的联动交互...略
透传属性 Attributes
透传:attribute
指的是传递给一个组件,却没有被该组件声明为props
或emits
的attribute
或者v-on事件监听器
。最常见的例子就是 class,style,id当一个组件以单个元素为根作渲染时,透传的attribute会自动被添加到根元素上
禁用透传属性
<script>
export default {
//禁止继承Attribute
inheritAttrs:false
}
</script>
插槽Slots
父组件使用子组件起始双标签包裹View
即可意图插入View
子组件中使用<slot>
标签即可接收父组件插入的view
并决定位置
<!-- 父组件示例 -->
<template>
<itemView><!-- 使用子组件 -->
<div>父插入的view</div>
</itemView>
</template>
<!-- 子组件示例1 -->
<template>
<div>我是子组件的DIV视图</div>
<!-- 使用父插入的view(如果有) -->
<slot/>
</template>
<!-- 子组件示例2-为slot设置默认视图 -->
<template>
<div>我是子组件的DIV视图</div>
<!-- 使用父插入的view(如果有) -->
<slot><a>默认view</a></slot>
</template>
渲染作用域
插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件板中定义的
具名插槽
子组件可以针对处理父组件传入的多个view
父组件将对应view使用<template v-slot:name>
包裹 (简写:#name
)
子组件使用<slot name="name">
接收处理对应view
<!-- 父组件示例 -->
<template>
<Item><!--使用子组建-->
<template v-slot:hr1>
<div>来自父组件的分割线1</div>
</template>
<template #button>
<button>来自父组件的按钮</button>
</template>
<template #hr2>
<div>来自父组件的分割线2</div>
</template>
</Item>
</template>
<!-- 子组件示例 -->
<template>
<!--处理接收到的指定view插槽-->
<slot name="hr2"/>
<div>我是子组件的DIV视图</div>
<slot name="button"/>
<slot name="hr1"/>
</template>
插槽内外数据传递
1,内部:
<slot>
标签内使用:属性名称="data"
绑定数据供外部获取2,外部:
<itemName>子标签
内使用v-slot="objName"
绑定数据对象 (简写#="objName"
)3,外部通过
objName.属性名称
获取数据
<!-- 父组件示例 接收子数据-->
<template>
<!-- 绑定slotProps对象-->
<itemView v-slot="obj">
<div>父:parent + 子:{{obj.dataName}}</div>
</itemView>
</template>
<!-- 子组件示例 向父发送数据-->
<template>
<slot :dataName="()=>{return 'child'}"/>
</template>
具名插槽内外数据传递
1,内部:
<slot name="指定name">
标签内使用:属性名称="data"
绑定数据供外部获取2,外部:<itemName>子标签内指定接收数据的插槽标签使用
v-slot="slotProps"
绑定数据对象3,外部通过
slotProps.属性名称
获取数据
<!-- 父组件示例 -->
<template>
<Item>
<template #hr="obj_hr">
<div>子数据:{{obj_hr.dataName}}</div>
</template>
</Item>
</template>
<!-- 子组件示例 -->
<template>
<slot name="hr" :dataName="()=>{return 'child'}"/>
</template>
组件生命周期
1,beforeCreate: 组件创建前
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
2,created: 组件创建后
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前尚不可用。
3,beforeMount: 组件渲染前
在挂载开始之前被调用:相关的 render 函数首次被调用。
4,mounted: 组件渲染后
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子函数。
5,beforeUpdate: 组件数据更新前-
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会导致额外的重新渲染。
6,updated: 组件数据更新后
由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用该钩子。
7,beforeDestroy: 组件卸载销毁前
在实例销毁之前调用。在这一步,实例仍然完全可用。
8,destroyed: 组件卸载销毁后
实例销毁后调用。该钩子函数被调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
*,errorCaptured: 捕获组件生命周期中的错误。
会向上冒泡,并且正常情况下会记录在控制台。
生命周期钩子函数 - 小结
创建期:
beforeCreate
,created
挂载区:
beforeMount
,mounted
更新期:
beforeUpdate
,updated
销毁期:
beforeUnmount
,unmounted
动态组件
一,使用<component>
指定/切换对应组件
使用 <component is="导入的组件名称"/>
绑定导入的指定组件名
绑定动态值:
<component :is="(()=>{return '指定的组件'})()"/>
二,使用逻辑渲染:v-if
,v-else
,v-else-if
,v-show
三,操作DOM(理论...略)
组件保活:
当使用
<component is="???"/>
在多个组件间切换时,使用<keep-alive>
包裹<component/>
保持活跃状态
<keep-alive >
<component :is="theView"/>
</keep-alive>
当使用逻辑渲染:
v-show
可以让组件不被卸载v-if
,v-else
,v-else-if
会卸载false组件
<template>
<div :class="useClass" v-if="index==='1'">
<h3>当前模块ID为{{ index }},是否需要保活-{{ keepAlive }}</h3>
<button @click="reItem">切换子组件-{{ keepAlive ? '' : '不' }}保活</button>
<button @click="keepAlive=!keepAlive">保活开关-{{ keepAlive }}</button>
<keep-alive v-if="keepAlive">
<component :is="theView" ref="theComponent"/>
</keep-alive>
<component :is="theView" ref="theComponent" v-else/>
</div>
<div :class="useClass" v-else>
<h3>当前模块ID为{{ index }},是否需要保活-{{ keepAlive }}</h3>
<button @click="reItem">切换子组件-{{ keepAlive ? '' : '不' }}保活</button>
<button @click="keepAlive=!keepAlive">保活开关-{{ keepAlive }}</button>
<div v-if="keepAlive">
<ItemA v-show="isA"/>
<ItemB v-show="!isA"/>
</div>
<div v-if="!keepAlive">
<ItemA v-if="isA"/>
<ItemB v-if="!isA"/>
</div>
</div>
</template>
<script>
import ItemA from "@/components/DynamicItem/ItemA.vue";
import ItemB from "@/components/DynamicItem/ItemB.vue";
export default {
components: {ItemB, ItemA},
data() {
return {
isA: true,
theView: 'ItemA',
keepAlive: false
}
},
props: ["index"],
methods: {
reItem() {
this.isA = !this.isA;
this.theView = (this.theView === 'ItemA' ? 'ItemB' : 'ItemA');
}
},
computed: {
useClass() {
return this.index === "1" ? "classBg1" : "classBg2"
},
}
}
</script>
<style scoped>
.classBg1 {
width: 300px;
height: 300px;
background: #62e83c;
text-align: center;
align-content: center;
}
.classBg2 {
width: 300px;
height: 300px;
background: #3cdbf5;
text-align: center;
align-content: center;
}
</style>
异步组件-优化组件性能
在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。
Vue 提供了defineAsyncComponent
方法来实现此功能
<script>
import { defineAsyncComponent } from "vue";
//异步加载组件
const ItemB = defineAsyncComponent(()=>import("@/components/DynamicItem/ItemB.vue"))
</script>
依赖注入
顶级组件向下注入依赖
<!--顶级组件向下注入依赖-->
<script>
export default {
//向下组件树注入依赖数据
provide:{
value:"from the top"
},
}
</script>
<!--任意子组件向上引用依赖数据-->
<script>
export default {
//向上组件树引用依赖数据
inject:{
value:{
default() {
//设置默认值
return "没有向上查找到依赖数据";
}
}
},
}
</script>
应用级注入依赖
在main.js
文件中使用app.provide("dateKey","dataValue")