一、 计算属性和方法的区别
- 计算属性:(computed)计算属性值会基于其响应式依赖被缓存,一个计算属性仅会在其响应式依赖更新时,才重新计算。
- 方法:(methods)方法调用宗师会在重渲染发生时再次执行函数
二、 侦听器
- watch:在watch中,函数名必须与侦听的数据对象保持一致,
<template>
<div class="count" @click="addCount">click me {{count}}</div>
</template>
<script>
// import Vue 不是必须的,需要手动指定 Vue 的版本时,可以解开注释
// import Vue from 'vue';
export default {
data() {
return {
count: 0,
};
},
methods: {
addCount() {
this.count += 1;
},
},
watch:{
count(newvalue,oldvalue){
console.log(newvalue)
console.log(oldvalue)
}
}
};
</script>
<style>
.count {
color: red;
}
</style>
三、 v-model
<input type="text" v-model.lazy="message" >
<p>{{message}}</p>
默认情况下,v-model会在每次input事件后更新数据,你可以添加lazy修饰符改为每次change事件后更新。 v-model也提供了修饰符:lazy,number,trim
四、模板引用-获取DOM操作
$ref : 元素可以使用ref获取元素,this.$refs.name
五、组件组成
组件最大的优势就是可复用性当使用构建步骤时,我们一般会将vue组件定义在一个单独的.vue文件中,这被叫做单文件组件(简称SFC)
**引用组件分为三个步骤:**
***//第一步:引入组件***
###### 1.在app.vue中,import mycompoent from "./compoents/mycompoent.vue"
***//第二步:注入组件***
###### 2.在components中,写入mycompoent
**//第三步:显示组件**
###### 3.在template中,写入组件
<mycompoent />
组件的注册方式
一个vue组件在使用前需要先被“注册”,这样vue才能在渲染模板时找到其对应的实现,组件注册有俩种方式:全局注册和局部注册全局注册:在main.js中注册组件
全局注册虽然方便,但是有以下几个问题:
1.全局注册,但并没有被使用的组件无法在生产打包时自动移出(也叫:tree-shaking),如果全局注册了一个组件,即使他没有被实际使用,他仍然会出现在打包后的JS文件中
2.全局注册在大型项目中使用项目的依赖关系变得不那么明确,在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性
局部注册需要使用 components 选项
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import { apiAxios, apiBaseUrl } from '../src/common/js/api';
const app = createApp(App);
// 将API基础URL和axios挂载到Vue实例上
app.config.globalProperties.$apiBaseUrl = apiBaseUrl;
app.config.globalProperties.$apiAxios = apiAxios;
// 全局注册组件
import SiteHeader from "./views/page/SiteHeader.vue";
app.component("SiteHeader", SiteHeader);
app.use(store).use(router).mount('#app');
组件的传递数据
props:['title'],父传子props传递数据,只能从父级传到子级,不能反其道而行 props是只读的数据,不允许修改
<p>{{ newval.name }}</p>
<p>{{ newval.age }}</p>
<ul>
<li v-for="(item, index) of arr" :key="index">{{ item }}{{ index }}</li>
</ul>
props: {
// 类型检查
arr: Array,
// 必填项
newval: {
type: Object,
required: true,
// 默认值
default: function () {
return {
name: '张三', age: 18
}
}
},
},
$emit子传父
子页面:
data() {
return {
msg: 'hello'
}
},
// 子组件向父组件传值,通过$emit()方法触发事件,并传递参数
// 父组件通过v-on监听子组件传递的事件,并接收参数
methods: {
clickhandled() {
this.$emit('someEvent', this.msg)
}
}
父页面
<AppSiteChild :newval="sscode" :arr="arr" @someEvent="gethandle" />
methods:{
gethandle(data){
console.log(data,'666');
}
}
组件之间相互动态实时获取数据 在子组件中,通过v-model创建一个动态变量,
<input type="text" v-model="seachData">
通过watch侦听器实时将最新的数据传递给父组件
data() {
return {
seachData:''
};
},
watch: {
seachData(newValue,oldValue){
// 将newValue发送给父组件
this.$emit('seachData',newValue)
}
},
emits: ['seachData'], // 声明组件可以发出的自定义事件
在父组件中接收自定义事件
<appSerch @seachData="getSeachData" />
getSeachData(data){
this.message = data
console.log(this.message);
}
六、vue中插槽slot的使用 元素是一个插槽的出口(slot outlet),标识了父元素提供的插槽内容(slot content)将在哪里被渲染
1. 插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的
2.具名插槽
.vue父级页面
<appBase >
<template v-slot:tempi>
<h3>第一个插槽内容</h3>
</template>
<template v-slot:tempo>
<h3>第二个插槽内容</h3>
</template>
</appBase>
.vue子级页面
<template>
<h3>顶部内容</h3>
<slot name="tempi"></slot>
<h5>中间内容</h5>
<slot name="tempo"></slot>
</template>
v-slot有对应简写的‘#’,因此<template v-slot:tempi> 也可以写成<template #tempi>,其意思就是将这部分模板片段传入子组件的tempi插槽中
3.插槽中传递数据(包含具名插槽传递数据)
//子组件传值
<template>
<h3>顶部内容</h3>
<slot name="tempi" :msg="message"></slot>
<h5>中间内容</h5>
<slot name="tempo" :obj="demo"></slot>
</template>
<script>
export default {
data () {
return {
message: '子组件的msg传给父元素,重新渲染到子组件的插槽中',
demo:{
name:'名字'
}
}
}
}
</script>
//父组件接收并渲染给子组件
<appBase>
<template #tempi="slotProps">
<h3>第一个插槽内容</h3>
{{ slotProps.msg }}
</template>
<template v-slot:tempo="slotPropsobj">
<h3>第二个插槽内容</h3>
{{ slotPropsobj.obj.name }}
</template>
</appBase>
七、vue生命周期 基础生命周期
/**
* vue生命周期
* 1.创建前/后 beforeCreate created
* 2.挂载前/后 beforeMount mounted
* 3.更新前/后 beforeUpdate updated
* 4.销毁前/后 beforeDestroy destroyed
* 5.keep-alive专属activated/deactivated
* 6.错误处理钩子 errorCaptured
* 7.路由专属 beforeRouteEnter(进入路由前) beforeRouteUpdate(更新路由前) beforeRouteLeave(离开路由前
*/
八、异步组件加载
因为vue在加载的时候会先加载完子组件之后,才把父组件给加载了,这样如果子组件加载时间过长,就会导致页面出现长时间的空白,使用异步组件就可以解决这个问题。
vue3提供了 defineAsyncComponent,它可以更简洁地定义异步组件。0只需要传递一个返回 import() 函数的参数,该函数会在需要时动态加载组件。这样可以减少手动编写异步加载的代码。 代码:
import { defineAsyncComponent, Suspense } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
);
export default {
// ...
components: {
AsyncComponent
},
// ...
template: `
<div>
<Suspense>
<AsyncComponent />
</Suspense>
</div>
`
};
九、依赖注入,父级组件传值给深层子组件
provide和inject,一个父组件相对于其所有的后代组件,会作为依赖提供者,任何后代的组件树,无论层级多深,都可以注入由父组件提供给整条链路的依赖
provide和inject只能由上到下的传递