0
点赞
收藏
分享

微信扫一扫

14、Vue组件进阶

phpworkerman 2022-03-19 阅读 84
vue.js

1、动态组件

针对以上问题我们可以使用v-if和v-show等方式来解决
在vue中我们还提供了一种解决方式,就是利用动态组件来实现

1、准备两个需要切换的组件

  • UserName.vue
<template>
  <div>
    <span>用户名:</span>
    <input type="text" name="" id="" />
    <span>密码:</span>
    <input type="text" name="" id="" />
  </div>
</template>

<script>
export default {};
</script>

<style>
</style>
  • UserInfo.vue
<template>
  <div>
    <div>
      <span>人生格言:</span>
      <input type="text" />
    </div>
    <div>
      <span>个人简介</span>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
</style>

2、引入到UseTab.vue注册

import UserName from "@/components/Demo01/UserName";
import UserInfo from "@/components/Demo01/UserInfo";
export default {

  // 注册组件
  components: {
    UserName,
    UserInfo,
  },
};

3、准备变量来承载要显示的"组件名"

  data() {
    return {
      //设置挂载点
      comName: "UserName",
    };
  },

4、设置挂载点<component>, 使用is属性来设置要显示哪个组件

 <component :is="comName"></component> 

5、点击按钮 – 修改comName变量里的"组件名"

 <button @click="comName='UserName'">账号密码填写</button>
    <button @click="comName='UserInfo'">个人信息填写</button>

6、完整代码

<template>
  <div>
    <button @click="comName='UserName'">账号密码填写</button>
    <button @click="comName='UserInfo'">个人信息填写</button>
    <p>下面显示注册的组件</p>
    <div class="contain">
      <component :is="comName"></component>
    </div>
  </div>
</template>

<script>
// 导入组件
import UserName from "@/components/Demo01/UserName";
import UserInfo from "@/components/Demo01/UserInfo";
export default {
  data() {
    return {
      //设置挂载点
      comName: "UserName",
    };
  },

  // 注册组件
  components: {
    UserName,
    UserInfo,
  },
};
</script>

<style lang="less" scoped>
.contain {
  width: 500px;
  height: 200px;
  border: 1px solid red;
}
</style>

【效果图】:
在这里插入图片描述
在这里插入图片描述

7、App.vue

<template>
  <div>
    <h1>动态组件的使用</h1>
    <UseTab></UseTab>
  </div>
</template>

<script>
// 导入组件
import UseTab from "@/components/Demo01/UseTab";
export default {
  components: {
    UseTab,
  },
};
</script>

<style>
</style>

2、组件缓存

1、问题演示

【代码修改】:

  • UserName.vue
export default {
  created() {
    console.log("username组件---创建了");
  },
  destroyed() {
    console.log("username组件---销毁了");
  },
};
</script>
  • UserInfo.vue
export default {
  created() {
    console.log("userInfo组件---创建了");
  },
  destroyed() {
    console.log("userInfo组件---销毁了");
  },
};
</script>

【结果图】:
在这里插入图片描述

2、问题解决

使用keep-alive内置的vue组件, 让动态组件缓存而不是销毁

【代码修改】:

      <keep-alive>
        <component :is="comName"></component>
      </keep-alive>

【效果图】:
在这里插入图片描述

3、组件插槽

vue提供组件插槽能力, 允许开发者在封装组件时,把不确定的部分定义为插槽

1、基本使用

  1. 组件内用<slot></slot>占位
  2. 使用组件时夹着的地方, 传入标签替换slot

2、折叠面板案例重新演示

  • 准备折叠面板组件
    在内容区域使用slot标签进行占位
<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
      <h4>芙蓉楼送辛渐</h4>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
    // 使用组件插槽占位
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
    };
  },
};
</script>

<style scoped>
h3 {
  text-align: center;
}

.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 1em;
}

.title h4 {
  line-height: 2;
  margin: 0;
}

.container {
  border: 1px solid #ccc;
  padding: 0 1em;
}

.btn {
  /* 鼠标改成手的形状 */
  cursor: pointer;
}

img {
  width: 50%;
}
</style>
  • 准备使用面板的组件
    导入面板,并且替换面板内部的内容
<template>
  <div id="container">
    <div id="app">
      <h3>案例:折叠面板</h3>
      //使用面板。并替换插槽内部的内容
      <Panel>
        <img src="../../assets/mm.gif" alt="" />
        <span>我是文字哦</span>
      </Panel>

      <Panel name="">
        <p>寒雨连江夜入吴,</p>
        <p>平明送客楚山孤。</p>
        <p>洛阳亲友如相问,</p>
        <p>一片冰心在玉壶。</p>
      </Panel>
    </div>
  </div>
</template>

<script>
import Panel from "@/components/Demo03/Panel";
export default {
  components: {
    Panel,
  },
};
</script>

<style lang="less" scoped>
#app {
  width: 400px;
  margin: 20px auto;
  background-color: #fff;
  border: 4px solid blueviolet;
  border-radius: 1em;
  box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);
  padding: 1em 2em 2em;
}
</style>
  • App.vue
<template>
  <div>
    <UserPanel></UserPanel>
  </div>
</template>

<script>
import UserPanel from "@/components/Demo03/UserPanel";
export default {
  components: {
    UserPanel,
  },
};
</script>

<style>
</style>

【效果图演示】:
在这里插入图片描述

3、插槽默认内容设置

<slot>夹着内容默认显示内容, 如果不给插槽slot传东西, 则使用<slot>夹着的内容在原地显示

【语法】:

<slot>默认内容</slot>

4、具名插槽

1、具名插槽基本使用

【语法】:

  1. slot使用name属性区分名字
  2. template配合v-slot:名字来分发对应标签

2、折叠面板案例修改

在这里插入图片描述
途中的#title是一种简写的方式,相当于v-click用@代替
在这里插入图片描述

5、作用域插槽

1、使用步骤

  1. 子组件, 在slot上绑定属性和子组件内的值
  2. 使用组件, 传入自定义标签, 用template和v-slot=“自定义变量名”
  3. scope变量名自动绑定slot上所有属性和值

2、折叠面板改造

  • 面板组件
    在这里插入图片描述
  • 使用面板组件
    在这里插入图片描述

3、作用域插槽案例

需求: 封装一个表格组件, 在表格组件内循环产生单元格

  • MyTable.vue
<template>
  <div>
    <table border="1">
      <thead>
        <tr>
          <th>序号</th>
          <th>姓名</th>
          <th>年龄</th>
          <th>头像</th>
        </tr>
      </thead>
      <thead>
        <tr v-for="(item, index) in list" :key="index">
          <td>{{ index + 1 }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
          <td>
            <slot :img="item">{{ item.headImgUrl }}</slot>
          </td>
        </tr>
      </thead>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [
        {
          name: "小传同学",
          age: 18,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
        },
        {
          name: "小黑同学",
          age: 25,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
        },
        {
          name: "智慧同学",
          age: 21,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
        },
      ],
    };
  },
};
</script>
  • UseTable.vue
<template>
  <div>
    <MyTable>
      <template v-slot="imgNew">
        <img :src="imgNew.img.headImgUrl" alt="" />
      </template>
    </MyTable>
  </div>
</template>

<script>
import MyTable from "@/components/Table/MyTable";
export default {
  components: {
    MyTable,
  },
};
</script>

<style>
img {
  width: 100px;
  height: 100px;
  border: 1px solid #333;
  border-radius: 50px;
  margin: 5px;
}
</style>
  • App.vue
<template>
  <div>
    <UseTable></UseTable>
  </div>
</template>

<script>
import UseTable from "@/components/Table/UseTable";
export default {
  components: {
    UseTable,
  },
};
</script>

<style>
</style>
举报

相关推荐

0 条评论