56-61 组件插槽、动态组件,异步组件

56-61 组件插槽、动态组件,异步组件

  • 插槽的基本使用
  • 具名插槽--v-slot
  • 渲染作用域、作用域插槽
    • 渲染作用域
    • 作用域插槽--使用子组件的数据
  • 动态组件
  • 异步组件-适用于大型项目加载时

插槽的基本使用

56-61 组件插槽、动态组件,异步组件_第1张图片
先写一个组件,然后将按钮注释,改为插槽,其中插槽可以编写默认内容,在应用组件时,将自定义元素写在组件中,就会替换slot的标签,十分灵活

  <body>
    <div id="app">
      <lk-box><button>点我</button></lk-box>
      <lk-box><input type="text" placeholder="输入名字"></lk-box>
    </div>
    <template id="box">
      <div style="background-color: red; width: 200px; height: 200px;margin:20px;">
        <h2>hhhh</h2>
        <p>like it</p>
        <!-- <button>点我</button> -->
        <!-- 预留插槽 -->
        <slot></slot>
      </div>
    </template>
    <script>
      const LkBox = {
     
        template: '#box',
      };
      const app = Vue.createApp({
     
        data() {
     
          return {
     };
        },
        components: {
     
          'lk-box': LkBox,
        },
        methods: {
     },
      }).mount("#app");
    </script>
  </body>

    <div id="app">
      <lk-box><button>点我</button></lk-box>
      <lk-box><input type="text" placeholder="输入名字"></lk-box>
    </div>

56-61 组件插槽、动态组件,异步组件_第2张图片

具名插槽–v-slot

当使用多个插槽时,要有具体的命名
先按照上面的方式,写三个插槽,查看效果,分别渲染了三次很明显不对

<body>
    <div id ="app">
        <lk-box>
            <h1>头部</h1>
            <h2>主要内容</h2>
            <h3>尾部</h3>
        </lk-box>

    </div>
    <template id="box">
        <div>
            <p>-----</p>
            <header>
                <!-- 放头部 -->
                <slot name="header">头部</slot>
            </header>
            <main>
                <!-- 放内容 -->
                <slot name="main">内容</slot>

            </main>
            <footer>
                <!-- 放页脚 -->
                <slot name="footer">页脚 </slot>
            </footer>
            <p>------</p>
        </div>
    </template>
    <script>
        const lkbox={
     
            template:'#box'
        };
     const app = Vue.createApp({
     
        data() {
     
            return{
     
            }
        },
        components: {
     
            'lk-box':lkbox
        },
        methods: {
     }
     }).mount('#app');
    </script>
</body>

56-61 组件插槽、动态组件,异步组件_第3张图片
正确写法
主要name要一一对应,使用v-slot的指令对应子组件的插槽

<body>
    <div id ="app">
        <!-- 错误调用 -->
        <!-- <lk-box>
            <h1>头部</h1>
            <h2>主要内容</h2>
            <h3>尾部</h3>
        </lk-box> -->
        <!-- 正确的 -->
        <lk-box>
            <template v-slot:header>
                <button>我是头部</button>
            </template>
            <template v-slot:main>
                <input type="text" placeholder="我是中间">
            </template>
            <template v-slot:footer>
                <button>我是尾部</button>
            </template>
        </lk-box>
    </div>
    <template id="box">
        <div>
            <p>-----</p>
            <header>
                <!-- 放头部 -->
                <slot name="header">头部</slot>
            </header>
            <main>
                <!-- 放内容 -->
                <slot name="main">内容</slot>

            </main>
            <footer>
                <!-- 放页脚 -->
                <slot name="footer">页脚 </slot>
            </footer>
            <p>------</p>
        </div>
    </template>
    <script>
        const lkbox={
     
            template:'#box'
        };
     const app = Vue.createApp({
     
        data() {
     
            return{
     
            }
        },
        components: {
     
            'lk-box':lkbox
        },
        methods: {
     }
     }).mount('#app');
    </script>
</body>

56-61 组件插槽、动态组件,异步组件_第4张图片
补充,默认插槽
当其中一个插槽没有命名,则当外部调用组件时,会显示的子组件中的里的内容
如果要使用外部传进来的,可以使用v-slot:default,默认对应这一个没有命名的slot进行替换
这里只黏贴了部分代码

 <template v-slot:default>
     <input type="text" placeholder="我是中间">
 </template>

组件里的插槽未命名

    <template id="box">
        <div>
            <p>-----</p>
            <header>
                <!-- 放头部 -->
                <slot name="header">头部</slot>
            </header>
            <main>
                <!-- 放内容 -->
                <slot>内容</slot>

            </main>
            <footer>
                <!-- 放页脚 -->
                <slot name="footer">页脚 </slot>
            </footer>
            <p>------</p>
        </div>
    </template>

效果:
56-61 组件插槽、动态组件,异步组件_第5张图片

渲染作用域、作用域插槽

渲染作用域

在这里插入图片描述

<body>
    <div id ="app">
        <lk-box v-show="isshow"></lk-box>
    </div>
    <template id="box">
        <div style="background-color: red;width: 200px;height: 200px;margin:20px">
            <button>点我</button>
        </div>
    </template>
    <script>
        const lkbox={
     
            data(){
     
                return{
     
                    isshow:false
                }
            },
            template:'#box'
        };
     const app = Vue.createApp({
     
        data() {
     
            return{
     
                isshow:true
            }
        },
        components: {
     
            'lk-box':lkbox
        },
        methods: {
     }
     }).mount('#app');
    </script>
</body>

56-61 组件插槽、动态组件,异步组件_第6张图片

作用域插槽–使用子组件的数据

一般传入的是父组件的数据,因为作用域的问题,父子组件的数据不能随意调用,当插槽中,需要由子组件的数据进行渲染,可采用作用域插槽的方式
在这里插入图片描述

  <body>
    <div id="app">
        <lk-box></lk-box>
        <p>---------</p>
        <lk-box>
            <template v-slot:default="slotProps">
                <span>{
     {
     slotProps}}</span>
                <span>{
     {
     slotProps.data.join('---')}}</span>
            </template>
        </lk-box>
    </div>
    <template id="box"> 
        <div style="background-color: red;width: 200px;height: 200px;margin:20px;">
            <slot :data="nameArr">
                <ul>
                    <li v-for="name in nameArr">{
     {
     name}}</li>
                </ul>
            </slot>
        </div>
    </template>
    <script>
      const lkbox = {
     
          data(){
     
              return{
     
                  nameArr:['张三','李四','王五']
              }
          },
        template: "#box",
      };
      const app = Vue.createApp({
     
        data() {
     
          return {
     
            msg: "hello",
          };
        },
        components: {
     
          'lk-box':lkbox  
        },
        methods: {
     },
      }).mount("#app");
    </script>
  </body>

如图1为正常调用,显示的默认插槽;现在想即调用子组件数据,并且也从父组件对插槽进行覆盖
这里slot添加data属性将子组件的数据传递出来

<slot :data="nameArr"> 

父组件应用时,定义一个slotProps的变量来接受子组件传过来的数组,对数据进行操作,添加----

        <lk-box>
            <template v-slot:default="slotProps">
                <span>{
     {
     slotProps}}</span>
                <span>{
     {
     slotProps.data.join('---')}}</span>
            </template>
        </lk-box>

56-61 组件插槽、动态组件,异步组件_第7张图片

动态组件

56-61 组件插槽、动态组件,异步组件_第8张图片

  <body>
    <div id="app"></div>
    <script>
      const app = Vue.createApp({
     
        data() {
     
          return {
     
              Citem:'lk-btn'
          };
        },
        methods: {
     
            change(){
     
                if(this.Citem==='lk-btn'){
     
                    this.Citem='lk-input'
                }else{
     
                    this.Citem='lk-btn'
                }
            }
        },
        template: 
        `
        
第一种写法,v-show写法,控制Citem进行显示

-----

`
, }); app.component("lk-btn", { template: ``, }); app.component("lk-input", { template: ``, }); app.mount("#app"); </script> </body>

第一种方式是通过v-show动态切换
56-61 组件插槽、动态组件,异步组件_第9张图片
第二种是通过vue提供的动态组件,动态绑定is属性取组件,简便的实现功能,并配合keepalive避免input失活无法保存状态的问题

        template: `
        

-----

`
,

56-61 组件插槽、动态组件,异步组件_第10张图片

异步组件-适用于大型项目加载时

56-61 组件插槽、动态组件,异步组件_第11张图片
参考链接1-ES6箭头函数和普通函数的区别
参考链接2-JavaScript Promise 对象
参考链接3-ECMAScript 6 简明教程
参考链接4-VUE defineAsyncComponent函数创建异步组件
使用settimeout模拟服务器加载渲染过程,defineAsyncComponent是vue3自带的函数,用于创建异步函数,

<body>
    <div id ="app">
        <async-item></async-item>

    </div>
    <script>
     const app = Vue.createApp({
     
        data() {
     
            return{
     
                msg:'hello'
            }
        },
        methods: {
     }
     });
    // 注册一个异步组件
    app.component('async-item',Vue.defineAsyncComponent(()=>{
     
        return new Promise((resolve,reject)=>{
     
            setTimeout(()=>{
     
                resolve({
     
                    template:`
`
}) },3000) }) })) app.mount('#app'); </script> </body>

效果:隔一段时间加载,模拟服务器渲染56-61 组件插槽、动态组件,异步组件_第12张图片

你可能感兴趣的