何以解忧
何以解忧
发布于 2024-05-02 / 283 阅读
1
0

Vue入门-学习笔记

学习资料

Vue教学视频链接:(点击跳转)

前提条件:

学习笔记

使用命令行创建Vue项目

  • 创建Vue项目:npm init vue@latest

  • 使用vite快速构建vue3+ts项目: npm create vite@latest 《项目名称》 --template ts

  • 按提示配置初始化项目

  • 运行项目:

  1. cd到项目:cd my_vue_project

  2. 安装:npm install

  3. 运行: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:

  1. 使用ref="标识值"属性给定一个标识值

  2. 使用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指的是传递给一个组件,却没有被该组件声明为propsemitsattribute或者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")


更多笔记,未完待续...


评论