您现在的位置是:首页 >其他 >vue-4:注册组件,组件传参,特殊属性ref $parent $root,透传,内置组件,自定义指令,mixins混入网站首页其他
vue-4:注册组件,组件传参,特殊属性ref $parent $root,透传,内置组件,自定义指令,mixins混入
注册组件,使用组件(项目中都是写component中)
为什么用组件:组件可以复用,每一个组件都是独立的,模板,数据,css样式互不影响
-
全局注册组件component:请勿滥用全局组件inx 因为 全局组件会造成组件名污染
-
vue2:Vue.component("组件名", { } ) 全局组件
-
vue3:app.component(“组件名字”, { } ) 全局组件
-
vue3: 局部注册组件components
-
<div id="app">
<my-header></my-header>
</div>
</html>
<script src="./lib/vue.global.js"></script>
<script>
let app = Vue.createApp({
data () {
return {
}
},
components: { // 局部组件的注册
// 组件的名字:对象形式的配置项
'my-header':{
template:`<div>{{msg}}</div>`,
data() {
return {
msg:"子组件"
}
},
}
}
})
app.mount("#app")
</script>
组件传参:解决组件之间数据无法共享(单向数据流原则)
-
vue中遵循是单向数据流,数据的流向是父到子,父组件的数据变化了,props中的数据就会立马的更新
-
props:父传子(只读属性):子使用父data中数据(props 校验)
-
父中子组件 v-bind(自定义属性)绑定属性样式,属性值就是父的数据传递给子组件
-
在子中定义一个 props来接收场地过来的属性名
-
接收的props上的所有的数据,都可以直接在子组件的模板上使用,也可以使用在选项中(记得带this)即:methods,watch,computed
-
<!-- 父传子 --> <div id="app"> {{fMsg}} <!-- 子组件 --> <my-kun :title="fMsg" :hei="list[0].title" :num="list[0].price"></my-kun> </div> </html> <script src="./lib/vue.global.js"></script> <script> let app = Vue.createApp({ data() { return { fMsg: '父的数据在此', list: [{ title: '小黑子', price: 5 }, { title: '坤坤', price: 5 }, { title: '凡凡', price: 5 }] } } }) app.component('myKun', { template: `<div> {{zMsg}}-----{{title}}-----{{hei}}-----{{num}} </div>`, // props: ['title','hei','num'], props: { 'title': [String], 'hei': String, // 自定义类型校验函数 'num': { validator(value) { // The value must match one of these strings return ['你好', '不好',5].includes(value) } }, }, data() { return { zMsg: '爱坤才会赢' } } }) app.mount('#app') </script>
-
-
emits:子传父(监听事件):父组件中使用子组件的数据(可以 emits 效验)
- 父中子组件绑定事件@myclick="fuMethod"
- 父中methods中使用 fuMethod( val ){ } 方法。用于接收子传递过来的数据,做处理
- 而 事件名 myclick则要去子组件中 emits中接收,绑定方法,然后使用(或者直接使用) 然后两种方式使用:
第一种: emits:['myClick'], //接收 methods:{ ziMethod(){ this.$emit('myclick', this.zMsg) } }, html中使用: @click="ziMethods"
第二种:接收后,直接html中使用 <button @click="$emit('someEvent')">click me</button> - - 父中接收,methods中的fuMethod方法做接收的处理。 处理完后根据:根据单向数据流原则,也自动更新视图
-
<!-- 父传子 --> <div id="app"> {{fMsg}} <!-- 子组件 --> <my-kun @myclick="fuMethod"></my-kun> </div> </html> <script src="./lib/vue.global.js"></script> <script> let app = Vue.createApp({ data() { return { fMsg: '父的数据在此', list: [{ title: '小黑子', price: 5 }, { title: '坤坤', price: 5 }, { title: '凡凡', price: 5 }] } }, methods: { fuMethod(msg) { console.log(111); this.fMsg = msg } } }) app.component('myKun', { template: `<div> {{zMsg}} <button @click="ziMethod">哈哈</button> </div>`, // 直接写template中 // <button @click="$emit('someEvent')">click me</button> // emits:["myclick"], emits: { // click: null, // 校验 submit 事件 'myclick': (payload) => { if (payload) { return true } else { console.warn('忘记传参了') return false } } }, data() { return { zMsg: '爱坤才会赢' } }, methods: { ziMethod() { this.$emit('myclick', this.zMsg) } } }) app.mount('#app') </script>
-
兄弟组件传值:
先实例化一个公共的通信对象eventBus.js,
其中一个兄弟组件通过$emit去发送触发事件 ,
一个组件通过$on接收监听事件
vue3:中没有明确的兄弟组件传值的方案,可以使用状态提升
(找到这两个组件共同的父级组件,然后通过父与子之间的传值实现)
//utils文件夹下:eventBus.js
import {createApp} from 'vue'
// 实例化通信对象,导出
export default createApp()
跨组件传值(父传给儿子或者孙子):依赖注入(provide ,injiect)
一个vue文件 provide只能写一个,写多个只有最后一个生效,所以,其他方法,
计算属性也是如此,自上而下执行代码,只有最后一个生效
特殊属性ref $parent $root
-
ref
用于注册元素或子组件的引用。子组件最终会渲染成标签,同时传递的数据绑定在这个标签上
数据可以通过 $attrs.属性名 来获取属性值 -
使用选项式 API,引用将被注册在组件的
this.$refs
对象里可以调用 -
放在标签上:获取的是所在标签的dom节点 放到组件上,获取子组件的方法属性
使用方法时记得方法要加()调用。不要重复打印
-
- $parent:写子组件内可以获取父组件的方法属性,有就获取,没有则为 null
- $root:写子组件内可以获取 根组件的方法属性,有就获取,没有就是它自己
透传(属性):Vue3:透传属性。透传又分为自动透传绑定,和手动绑定两种。
什么是透传属性? 透传属性指组件在使用的时候,作用在组件上的属性,会被向下流动,绑定到组件内的标签中。
透传:父组件传递数据给子组件时,子组件接收父组件传递的属性 $attrs
透传作用:::
- attribute继承:子继承父:eg:class,id,style,属性,事件等头可以透传到组件内的标签中。
- 对class和style合并
v-on监听继承
- 禁用透传属性是否继承属性: inheritAttrs: false
- 多根节点的继承:子组件使用props接收父组件传递的属性
内置组件
<KeepAlive> 缓存组件:用于包裹动态切换组件
<KeepAlive> 包裹动态组件时,会缓存不活跃的组件实例,而不是销毁它们。避免重复渲染组件(性能优化)
<component :is='coms[index]' /> 判断渲染哪个组件
is:特殊Attribute用于绑定[动态组件]
//动态组件:包裹挂载点即可
<keep-alive>
<component :is="Com"></component>
</keep-alive>
//路由:包裹路由出口即可
<keep-alive>
<router-view/>
</keep-alive>
//属性:如果 我把两个都写了 excloud的优先级大于incloude
include 你要缓存谁
exclude 你不想缓存谁
<keep-alive exclude="Db,xxxxx,cccc">
<!-- 设置动态组件的挂载点 -->
<component :is="com"></component>
</keep-alive>
#### 钩子函数
activated:在进入到被kepp-alive管理的组件时候触发
deactivated:在离开被kepp-alive管理的组件时候触发
替代 `mounted`挂载后 和 `unmounted`销毁后。
<template>
<div>
aaaaaaaa
<input type="text" />
</div>
</template>
<script>
export default {
activated() {
console.log("进入到了被keep-alive管理的组件中了");
},
deactivated() {
console.log("离开到了被keep-alive管理的组件中了");
},
};
</script>
动画组件 <Transiton />:里边只能放一个标签或者组件(使用vue官网查看)
name=" ":有名就写,没有就默认 mode="out-in"
一共有 6 个应用于进入与离开过渡效果的 CSS class
<Transition>
<p v-if="show">hello</p>
</Transition>
/* 下面我们会解释这些 class 是做什么的 */
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
插槽 <slot /> 组件: 自定义组件里内容 (借用一个链接详细)
如果在组件的开关标签中插入内容 默认是不显示的(组件是一个完整的独立的个体 如果没有特殊设置 那么没有办法向组件中插入内容) slot用来混合父组件与子组件自己的模板
默认插槽 <slot />
具名插槽 <slot name = "" />
自定义指令directive + 插件plugins
局部指令:通过directives: { 插件名:{ 钩子函数 } } 选项来定义,只能在当前组件中使用
指令的功能:取决指令钩子的钩子函数 created,mouted,updated......
eg: 当一个 input 元素被 Vue 插入到 DOM 中后,它会被自动聚焦
全局指令: 全局指令 v-指令名使用,通过app.directive( 'cals' { })方法来定义,可以在任何组件中使用,指令的功能:取决指令钩子的钩子函数 created,mouted,updated......
-
-
//a export default{ install(app){ app.directive('focus',{ // 绑定元素的父组件 // 及他自己的所有子节点都挂载完成后调用 mounted(el, binding, vnode, prevVnode) { el.focus(); //聚焦 }, }) } }
// b export default{ install(app){ app.directive('cal',{ // 绑定元素的父组件 // 及他自己的所有子节点都挂载完成后调用 mounted(el, binding, vnode, prevVnode) { el.value = el.value * 10 + '没钱' // 加钱 }, }) } }
<template> <div class="childa"> <!-- <h1 ref="title">{{ count }}</h1> --> childa组件 <input v-focus v-calc type="text" :value="4">哎哎哎啊 <input type="text" v-sss :value="6">哎哎哎啊 <h1 ref="title">{{ count }}</h1> <button @click="handleClick">传值</button> </div> </template> <script> export default { data() { return{ p:'123', count:3 } }, methods:{ handleClick(){ this.count++, // console.log(this.$refs.title.innerHTML); this.$nextTick(()=>{ console.log(this.$refs.title.innerHTML); }) } }, directives: { //自定义局部指令,只能在当前组将中使用 // 在模板中启用 v-focus focus:{ // 在绑定元素的父组件 // 及他自己的所有子节点都挂载完成后调用 mounted(el, binding, vnode, prevVnode) { console.log(el); el.focus() } }, sss:{ // 在绑定元素的父组件 mounted(el, binding, vnode, prevVnode) { el.value = el.value * 7+'元' } } } } </script>
-
mixins :混入
作用:抽离多个组件的公共代码(选项),避免代码冗余
使用 :混入的公共代码会出现在组件的选项位置
import导入mixins路径,混入:data同级自动混入,可以直接使用mixins里的方法属性了
export default{
// 能写在这里的都是组件已知选项 watch filter directives components data
methods:{
saveIndex(i){
this.index = i
}
},
computed:{
calc(){
return 2**10
}
}
}
<footer>
<span @click="saveIndex(index)" v-for="item, index in btns" :key="index">{{ item }}</span>
</footer>
// 导入mixins
import mixins from './mixins/index';
// 应用混入
mixins: [mixins],
methods: {
// 这个可以省略了。
// saveIndex(i) {
// this.index = i
// }
},
两个核心API:(不常用)
$forceUpdate():让组件强制更新(极端更新不了情况,自己写错了)
$nextTick():可以让特定代码在组件的 下次更新周期到 之后再执行
<button @click="handleClick">传值</button>
methods:{
handleClick(){
this.count++,
// console.log(this.$refs.title.innerHTML);
this.$nextTick(()=>{
console.log(this.$refs.title.innerHTML);
})
}
},