Vue3组件详情
- 一、父组件向子组件传值 ref、props
- 二、子组件向父组件传值 emit
- 三、子组件向父组件传值 v-model
- 四、setup语法糖
- 1、基本用法
- 2、data和methods
- 3、计算属性 computed
- 4、监听器 watch、watchEffect
- 5、自定义指令 directive
- 6、import导入的内容可以直接使用
- 7、声明props和emit
- 8、父组件获得子组件的数据(等同于Vue2.0中的$ref)
- 9、provide和inject传值
- 10、对await异步支持
- 11、nextTick
- 12、全局属性 globalProperties
- 13、与普通< script >标签一起使用
- 14、v-memo新指令
- 五、Vue3生命周期
一、父组件向子组件传值 ref、props
// 父组件
<Son :showDialogVisible="showDialogVisible" />
<script>
import {defineComponent,ref} from 'Vue';
setup(){const showDialogVisible=ref(true);return {showDialogVisible}
}
</script>
<script>
// 子组件
import {defineComponent,ref} from 'Vue';
export default defineComponent({name:"",props:{showDialogVisible:Boolean},setup(props){return {props}}
})
</script>
二、子组件向父组件传值 emit
子组件中:
由于Vue数据传递时单向数据流,子组件没有权利修改父组件传递过来的数据,只能用emit通知父组件去修改。
<script>// 子组件setup(props,context){context.emit('setShow',false)return;}...或者...setup(props,{emit}){emit('setShow',false)return;}
</script>
// 父组件
<Son :showDialogVisible="showDialogVisible"@setShow="setShowDialogVisible" />
<script>
import {defineComponent,ref} from 'Vue';
setup(){const showDialogVisible=ref(true);const setShowDialogVisible=(bool)=>{showDialogVisible=bool;}return {showDialogVisible,setShowDialogVisible}
}
三、子组件向父组件传值 v-model
如果子组件向父组件传的值正好是父组件向子组件传的值,可以直接在该属性上进行双向绑定。
// 子组件
// 直接修改从props中拿到的数据;context.emit('update:showDialogVisible',false)
</script>
// 父组件
<Son v-model:showDialogVisible="showDialogVisible"/>
<script>
四、setup语法糖
在vue2.0时期,组件里定义的各类变量,方法,计算属性等是分别放到data,methods,computed选项里。
setup是vue3.0后推出的语法糖,按需引入computed,watch,directive等,一个业务逻辑可以编写在一起,让代码更加简洁便于浏览。
1、基本用法
<script setup>console.log('Hello World');
</script>
只需在 < script > 里添加一个setup属性,编译时会把 < script setup> < / script >里的代码编译成一个setup函数。
普通的 < script > 只会在组件被首次引入的时候执行一次,< script setup> 里的代码会在每次组件实例被创建的时候执行。
2、data和methods
< script setup> 里声明的变量和函数,不需要return暴露出去,就可以直接在template使用。
<script setup>import {ref,reactive} from 'vue';const msg = "Hello World";//普通变量// 响应式变量let num = ref(11); //ref 声明基本变量类型const obj = reactive({//reactive 声明对象类型变量:Object,Array,Datekey:"this is a object"})function getName(){}
</script>
3、计算属性 computed
<script setup>import {ref,computed} from 'vue';let num = ref(0); const countPlus = computed(()=>{return num.value+1;})
</script>
4、监听器 watch、watchEffect
// watch
<script setup>import {ref,reactive,watch} from 'vue';// 监听reflet num = ref(0); watch(num,(newval,oldval)={// ...})// 监听reactiveconst obj = reactive({key:"this is a object"})watch(obj.key,(newval,oldval)={// ...},{immediate:true,// 立即执行,默认falsedeep:true,//深度监听,默认false})const onChange = function () {num.value++;obj.key="this change"}
</script>
watchEffect :Vue3.0新增的监听属性的方法,与watch的区别在于,watchEffect不需要指定监听对象,回调函数里可直接获取到修改后的属性的值。
<script setup>import {ref,reactive,watchEffect} from 'vue';let num = ref(0); const obj = reactive({key:"this is a object"})setTimeout( ()=> {num.value++;obj.key="this change"})watchEffect((newval,oldval)=>{console.log("修改后的count",count.value);console.log("修改后的obj",obj.key);})
</script>
5、自定义指令 directive
以vNameDirective的形式来命名本地自定义指令,可以直接在模板中使用。
<template><h1 v-my-directive>今天的日记</h1>
</template>
<script setup>
// 导入指令可重命名
// import {myDirective as vMyDirective} from './MyDirective.js'
// 自定义指令
const vMyDirective={beforeMount:(el)=>{// 元素上做一些操作}
}
</script>
6、import导入的内容可以直接使用
导入的模快内容,不需要通过method来暴露它;
导入外部组件,不需要通过components注册使用;
7、声明props和emit
// Child.vue
<template><h1>信息:{{info}}</h1><el-button @click="onChange">点击</el-button>
</template>
<script setup>
import {defineProps,defineEmits} from 'vue';
// 声明Props
const props =defineProps({info:{type:String,default:""}
})
// 声明Emits
const $emit = defineEmits(['changeInfo']);
const onChange=function(){$emit('changeInfo','child返回值')
}
</script>
// Parent.vue
<template><Child :info="msg" @changeInfo="onAction"></Child>
</template>
<script setup>
import {ref} from 'vue';
import Child from './Child.vue'
const onAction=function(event){console.log(event);
}
</script>
8、父组件获得子组件的数据(等同于Vue2.0中的$ref)
父组件想要通过ref获取子组件的变量或函数,子组件须使用defineExpose暴露出去。
// Child.vue
<script setup>import {ref,define} from 'vue';const info = ref('I am child');const onChange = function(){console.log('')};defineExpose({info,onChange})
</script>
// Parent.vue
<template><Child ref="childRef"></Child><el-button @click="onAction">点击</el-button>
</template>
<script setup>import {ref} from 'vue';import Child from './Child.vue'const childRef = ref();const onAction = function(){console.log(childRef.value.info)console.log(childRef.value.onChange());};
</script>
9、provide和inject传值
无论组件层次结构有多深,父组件都可以通过provide选项来为其所有子组件提供数据。
// Parent.vue
<template><Child></Child>
</template>
<script setup>import {ref,provide} from 'vue';import Child from './Child.vue'
const msg = ref('Hello,my son');
const onShow = function(){...};
provide('myprovide',{msg,onShow})
</script>
// Child.vue
<template><el-button @click="getDate">点击获取父组件的值</el-button>
</template>
<script setup>import {inject} from 'vue';const provideState = inject('myProvide');const getDate = function(){console.log(provideState.msg);console.log(provideState.onShow());}
</script>
10、对await异步支持
< script setup>中可以使用顶层await,结果代码会被编译成async setup()。例子:
<script setup>const post = await fetch('/api/post/tabledata').then(res=>{})
</script>
11、nextTick
//方式一
<script setup>
import {nextTick} from 'vue';
nextTick(()=>{});// Dom已更新
</script>
//方式二
<script setup>
import {nextTick} from 'vue';
await nextTick();// nextTick是一个异步函数,返回一个Promise实例
</script>
12、全局属性 globalProperties
// main.js
import {createApp} from 'vue';
import App from './App.vue';
const app = createApp(App);
// 定义一个全局属性
app.config.globalProperties.global="全局属性";
app.$mount("#app");
<script setup>
//组件内使用
import {getCurrentInstance} from 'vue';
const { proxy } = getCurrentInstance();//获取Vue实例
console.log(proxy.$global);//输出
</script>
13、与普通< script >标签一起使用
可以与普通< script>标签一起使用,但是以下一些情况不会使用到:
①无法在<script setup>声明的选项 ,例如inheritAttrs 或通过插件启用的自定义的选项;
②声明命名导出,< script setup >定义的组件果默认以文件各作为组件名.
③运行副作用或者创建只需要执行一次的对象
< script >
//普通< script >,在模块范围下执行(只执行一次)runSideEffectOnce();
// 声明额外的选项
export default {name :'ComponentName ',//组件重命名inberitAttrs:false ,customOptons:{}
}
</ script ><script setup )
//在 setup ()作用域中执行(对每个实例皆如此)
<script)
14、v-memo新指令
该指令与 v - once 类似, v - once 是只渲染一次之后的更新不再渲染,而 v - memo 是根据条件来渲染。该指令接收一个固定长度的数组作为依赖值进行记忆对比,如果数组中的每个值都和上次渲染的时候相同,则该元素(含子元素)不刷新。
①应用于普通元素或组件
< template >
< div v-meno ="[valueA ,valueB]">…</ div >//普通元素
< component v-memo ="[valueA , valueB]"></ component >//组件
< /template >< script setup )import component from ".../components/component.vne "
< /script >```
当组件重新渲染的时候,如果 valueA 与 valueB 都维持不变,那么对这个< div >以及它的所有子节点的更新都将被跳过。
②结合 v - for 使用
v - memo 仅供性能敏感场景的针对性优化,会用到的场景应该很少。渲染 v - for 长列表(长度大于1000)可能它是最有用的场景:
< template >< div v-for =" item in list " :key =" item.id " v-memo ="[ item.id == selected ]">< p > ID : {{item.id}}-selected : {{item.id == selected}}< /p >< / div>
</ template >
当 selected 发生变化时,只有 item . id === selected 的该项重新渲染,其余不刷新。