您现在的位置是:首页 >其他 >vue-4:注册组件,组件传参,特殊属性ref $parent $root,透传,内置组件,自定义指令,mixins混入网站首页其他

vue-4:注册组件,组件传参,特殊属性ref $parent $root,透传,内置组件,自定义指令,mixins混入

憨憨404 2024-06-17 10:14:41
简介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

  1. ref 用于注册元素或子组件的引用。子组件最终会渲染成标签,同时传递的数据绑定在这个标签上
    数据可以通过 $attrs.属性名   来获取属性值

  2. 使用选项式 API,引用将被注册在组件的 this.$refs 对象里可以调用

  3. 放在标签上:获取的是所在标签的dom节点 放到组件上,获取子组件的方法属性

    使用方法时记得方法要加()调用。不要重复打印


  4. - $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 = "" />

一文详解Vue插槽slot的使用与案例展示,看完就彻底明白了_slot 案例_唯一的阿金的博客-CSDN博客目录一、插槽的含义二、插槽的三种使用方法1.默认插槽2.具名插槽3.作用域插槽4.版本变化插槽slot在实际的项目开发中是经常使用的,主要分为三大类:默认插槽、具名插槽和作用域插槽,也是比较容易上手的。一、插槽的含义插槽slot是写在子组件的代码中,供父组件使用的占位符。在代码中,大致写为如下的形式,后面会进行详细的写法介绍。<slot> </slot>插槽其实就是在写slot的地方挖个坑,等着组件的使用者,即父组...https://blog.csdn.net/czjl6886/article/details/122094040#:~:text=%E4%BA%8C%E3%80%81%E6%8F%92%E6%A7%BD%E7%9A%84%E4%B8%89%E7%A7%8D%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%201%201.%E9%BB%98%E8%AE%A4%E6%8F%92%E6%A7%BD%20%E6%9C%89%E4%B8%A4%E4%B8%AA%E7%BB%84%E4%BB%B6%EF%BC%8CApp%E6%98%AF%E7%88%B6%E7%BB%84%E4%BB%B6%EF%BC%8CChild%E6%98%AF%E5%AD%90%E7%BB%84%E4%BB%B6%20%E7%88%B6%E7%BB%84%E4%BB%B6%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%20%3Ctemplate%3E%20%3Cdiv%20class%3D%22parent%22%3E,3.%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD%20%E5%A6%82%E6%9E%9C%E6%95%B0%E6%8D%AE%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BD%86%E6%A0%B9%E6%8D%AE%E6%95%B0%E6%8D%AE%E7%94%9F%E6%88%90%E7%9A%84%E7%BB%93%E6%9E%84%E9%9C%80%E8%A6%81%E7%BB%84%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E8%80%85%E6%9D%A5%E5%86%B3%E5%AE%9A%EF%BC%8C%E6%88%91%E4%BB%AC%E5%B0%B1%E9%9C%80%E8%A6%81%E7%94%A8%E5%88%B0%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD%EF%BC%8C%E5%90%8C%E6%97%B6%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E5%A4%9A%E7%A7%8D%E7%BB%93%E6%9E%84%E3%80%82%20%E4%BE%8B%E5%A6%82%EF%BC%9Agames%E6%95%B0%E6%8D%AE%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD%EF%BC%8C%E4%BD%86%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%E6%89%80%E9%81%8D%E5%8E%86%E5%87%BA%E6%9D%A5%E7%9A%84%E7%BB%93%E6%9E%84%E7%94%B1%E7%88%B6%E7%BB%84%E4%BB%B6App%E5%86%B3%E5%AE%9A%20%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD%EF%BC%8C%E4%BD%BF%E7%94%A8%20%3Cslot%20%3Agames%3D%22games%22%3E%20%E6%8C%87%E6%98%8E%E4%BD%BF%E7%94%A8%E4%BB%80%E4%B9%88%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%B9%B6%E5%B0%86%E6%95%B0%E6%8D%AE%E4%BC%A0%E7%BB%99%E6%8F%92%E6%A7%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E8%80%85%20

自定义指令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);
      })
    }
  },

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。