8.Vue组件

组件的初始化

全局注册:

<div id="app">
    <ksd-button></ksd-button>
    <ksd-time></ksd-time>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.component("ksdButton", {
        template: "<button>登录</button>",
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.component("ksdTime", {
        template: "<div>我是时间</div>",
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.mount("#app");
</script>

局部注册:

<div id="app">
    <ksd-button></ksd-button>
    <ksd-time></ksd-time>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        },
        components: {
            "KsdButton": {
                template: "<button>登录</button>",
                data() {
                    return {
                    }
                },
                created() {
                },
                methods: {
                }
            },
            "KsdTime":{
                template:"<div>我是时间</div>",
                data() {
                    return {
                    }
                },
                created() {
                },
                methods: {
                }
            }
        }
    }).mount("#app");
</script>

组件的特点
1:复用性。

2:隔离性。

<div id="app">
    <ksd-button></ksd-button>
    <ksd-button></ksd-button>
    <ksd-button></ksd-button>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.component("KsdButton", {
        template:"<button @click='countNum'>登录 { {count} }</button>",
        data() {
            return {
                count: 1
            }
        },
        created() {
        },
        methods: {
            countNum() {
                this.count++;
            }
        }
    });
    app.mount("#app");
</script>

在这里插入图片描述

父传子 - 自定义属性 props

书写规范:

1:属性名称全小写。

2:props 使用对象形式,不使用数组形式。

3:props 指定 type 如果错误,浏览器会提示警告不会报错,它不会影响 vue 的渲染。

4:使用组件自定义属性,属性可以直接通过指令和插值表达式使用,将其看成正常的 div 即可。

<div id="app">
    <ksd-button :ksdtext="num" :users="users"></ksd-button>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
                num: 1234,
                users: [1, 2, 3, 4]
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.component("ksdButton", {
        props: {
            ksdtext: {
                type: Number,
                required: true
            },
            users: Array
        },
        template: "<button @click='countNum' v-for='(user, index) in users'>{ {ksdtext} } == { {count} }</button>",
        data() {
            return {
                count: 1
            }
        },
        created() {
        },
        methods: {
            countNum() {
                this.count++;
            }
        }
    });
    app.mount("#app");
</script>

在这里插入图片描述

子传父 - 自定义事件 $emit

<div id="app">
    <ksd-load-more @loadmore="loadMoreUsers"></ksd-load-more>
    <p v-for="(user, index) in parentUsers" :key="user.id">
        <span>{ {user} }</span>
    </p>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
                parentUsers: []
            }
        },
        methods: {
            loadMoreUsers(users) {
                this.parentUsers = users;
            }
        }
    });
    app.component("KsdLoadMore", {
        template: `<div><button @click="loadMore">加载更多</button></div>`,
        methods: {
            loadMore() {
                this.$emit("loadmore", [{ id: 1, name: "zhangsan" }]);
            }
        }
    });
    app.mount("#app");
</script>

在这里插入图片描述

执行流程:
在这里插入图片描述

封装组件 - ksd-button

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ksd-button</title>
    <link rel="stylesheet" href="css/ksdui.css">
    <link rel="stylesheet" href="//at.alicdn.com/t/font_2882935_q0cj641ukuh.css">
</head>
<body>
<div id="app">
    <ksd-button>默认按钮</ksd-button>
    <ksd-button type="primary" icon="vip1">主要按钮</ksd-button>
    <ksd-button type="success" icon="setting" round>成功按钮</ksd-button>
    <ksd-button type="info" icon="28" round>信息按钮</ksd-button>
    <ksd-button type="warning" icon="houtai12">警告按钮</ksd-button>
    <ksd-button type="danger" icon="xihuan" round>危险按钮</ksd-button>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
            }
        },
        created() {
        },
        methods: {
        }
    });
    app.component("ksdButton", {
        props: {
            type: {
                type: String,
                default: "default",
            },
            icon: {
                type: String,
                default: "default",
            },
            round: {
                type: Boolean,
                default: false,
            }
        },
        template: "<button type='button' class='ksd-button' :class='[type ? `ksd-button--${type}` :  ``, round ? `is-round` : ``]'>" +
                      "<span>" +
                        "<i v-if='icon' :class='`iconfont icon-${icon}`'></i>" +
                        "<slot></slot>" +
                      "</span>" +
                  "</button>",
    });
    app.mount("#app");
</script>
</body>
</html>

在这里插入图片描述

封装组件 - ksd-page

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ksd-page</title>
    <link rel="stylesheet" href="css/ksdui.css">
</head>
<body>
<div id="app">
    <ksd-page
            :page-index="currentPage"
            :total="count"
            :is-go="false"
            :is-total="false"
            :page-size="pageSize"
            @change="pageChange">
    </ksd-page>
    <ksd-page
            :page-index="currentPage"
            :total="count"
            :is-go="true"
            :is-total="true"
            :page-size="pageSize"
            @change="pageChange">
    </ksd-page>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
                count: 100,
                pageSize: 10,
                currentPage: 1,
                items: []
            }
        },
        created() {
        },
        methods: {
            pageChange(pageNo) {
            }
        }
    });
    app.component("ksdPage", {
        props: {
            perPages: {
                type: Number,
                default: 5
            },
            pageIndex: {
                type: Number,
                default: 1
            },
            pageSize: {
                type: Number,
                default: 10
            },
            total: {
                type: Number,
                default: 1
            },
            isGo: {
                type: Boolean,
                default: false
            },
            isTotal: {
                type: Boolean,
                default: false
            }
        },
        template: "<div><ul class=\"ksd-paging\">\n" +
            "        <!-- prev -->\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--prev', {'paging-item--disabled' : index == 1}]\"\n" +
            "        @click=\"prev\">上一页</li>\n" +
            "\n" +
            "        <!-- first -->\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--first', {'paging-item--disabled' : index == 1}]\"\n" +
            "        @click=\"first\">首页</li>\n" +
            "\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--more']\"\n" +
            "        v-if=\"showPrevMore\">...</li>\n" +
            "\n" +
            "        <li\n" +
            "        :class=\"['paging-item', {'paging-item--current' : index == pager}]\"\n" +
            "        v-for=\"pager in pagers\"\n" +
            "        @click=\"go(pager)\">{ {pager} }</li>\n" +
            "\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--more']\"\n" +
            "        v-if=\"showNextMore\">...</li>\n" +
            "\n" +
            "        <!-- last -->\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--last', {'paging-item--disabled' : index == pages}]\"\n" +
            "        @click=\"last\">尾页</li>\n" +
            "\n" +
            "        <!-- next -->\n" +
            "        <li\n" +
            "        :class=\"['paging-item', 'paging-item--next', {'paging-item--disabled' : index == pages}]\"\n" +
            "        @click=\"next\">下一页</li>\n" +
            "        <li v-if='isGo' :class=\"['paging-item', 'paging-item--next']\"><input class='pageinput' type='text' v-model='index'></li>\n" +
            "        <li v-if='isTotal' :class=\"['paging-item', 'paging-item--next']\">共{ {total} }条</li>\n" +
            "    </ul></div>",
        methods: {
            toPage() {
                this.go(this.index)
            },
            prev() {
                if (this.index > 1) {
                    this.go(this.index - 1)
                }
            },
            next() {
                if (this.index < this.pages) {
                    this.go(this.index + 1)
                }
            },
            first() {
                if (this.index !== 1) {
                    this.go(1)
                }
            },
            last() {
                if (this.index != this.pages) {
                    this.go(this.pages)
                }
            },
            go(page) {
                if (this.index !== page) {
                    this.index = page
                    //父组件通过change方法来接受当前的页码
                    this.$emit('change', this.index)
                }
            }
        },
        computed: {
            pages() {
                return Math.ceil(this.size / this.limit)
            },
            pagers() {
                const array = []
                const perPages = this.perPages * 1
                const pageCount = this.pages * 1
                let current = this.index * 1
                const _offset = (perPages - 1) / 2
                const offset = {
                    start: current - _offset,
                    end: current + _offset
                }
                if (offset.start < 1) {
                    offset.end = offset.end + (1 - offset.start)
                    offset.start = 1
                }
                if (offset.end > pageCount) {
                    offset.start = offset.start - (offset.end - pageCount)
                    offset.end = pageCount
                }
                if (offset.start < 1) offset.start = 1
                this.showPrevMore = (offset.start > 1)
                this.showNextMore = (offset.end < pageCount)
                for (let i = offset.start; i <= offset.end; i++) {
                    array.push(i)
                }
                return array
            }
        },
        data() {
            return {
                index: this.pageIndex,
                limit: this.pageSize,
                size: this.total || 1,
                showPrevMore: false,
                showNextMore: false
            }
        },
        watch: {
            pageIndex(val) {
                this.index = val || 1
            },
            pageSize(val) {
                this.limit = val || 10
            },
            total(val) {
                this.size = val || 1
            }
        }
    });
    app.mount("#app");
</script>
</body>
</html>

在这里插入图片描述

封装组件 - ksd-loading

<!DOloadingType html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ksd-loading</title>
    <link rel="stylesheet" href="css/ksdui.css">
    <style>
        .loadingbox { text-align: center; }
    </style>
</head>
<body>
<div id="app">
    <ksd-loading :load-type="0" :ctype="2" :load-text="loadText"></ksd-loading>
    <ksd-loading :load-type="0" :ctype="1" :bgclor="'red'" :load-text="loadText"></ksd-loading>
    <ksd-loading :load-type="0" :ctype="2" :bgclor="'red'" :load-text="loadText"></ksd-loading>
</div>
<script src="js/vue.global.js"></script>
<script>
    var app = Vue.createApp({
        data() {
            return {
                loadText: ["正在来的路上...", "亲已经没有了...", "亲,家底被你掏空了..."]
            }
        }
    });
    app.component("KsdLoading", {
        props: {
            ctype: {
                type: Number,
                default: 1
            },
            bgclor: {
                type: String,
                default: "#171915"
            },
            loadType: Number,
            loadText: {
                type: Array,
                default: ["数据加载中...", "数据加载完毕...", "亲,我是有底线的..."]
            }
        },
        template: `
              <div class="loadingbox">
                  <div v-if="loadType == 2">{ {loadText[2]} }</div>
                  <div v-if="loadType == 1">{ {loadText[1]} }</div>
                  <div v-if="loadType == 0">{ {loadText[0]} }</div>
                  <div v-if="loadType == 0">
                    <div class="spinner2" :style='{"background": bgclor}' v-if="ctype == 2"></div>
                    <div class="spinner"  v-if="ctype == 1">
                      <div class="spinner-container container1">
                        <div class="circle1" :style='{"background": bgclor}'></div>
                        <div class="circle2" :style='{"background": bgclor}'></div>
                        <div class="circle3" :style='{"background": bgclor}'></div>
                        <div class="circle4" :style='{"background": bgclor}'></div>
                      </div>
                      <div class="spinner-container container2">
                        <div class="circle1" :style='{"background": bgclor}'></div>
                        <div class="circle2" :style='{"background": bgclor}'></div>
                        <div class="circle3" :style='{"background": bgclor}'></div>
                        <div class="circle4" :style='{"background": bgclor}'></div>
                      </div>
                      <div class="spinner-container container3">
                        <div class="circle1" :style='{"background": bgclor}'></div>
                        <div class="circle2" :style='{"background": bgclor}'></div>
                        <div class="circle3" :style='{"background": bgclor}'></div>
                        <div class="circle4" :style='{"background": bgclor}'></div>
                      </div>
                    </div>
                  </div>
              </div>
            `
    });
    app.mount("#app");
</script>
</body>
</html>

在这里插入图片描述

Vue-cli 中的使用

1:搭建 vue-cli 脚手架。

npm install -g @vue/cli
# OR
yarn global add @vue/cli
# OR
npm install -g cnpm --registry=https://registry.npmmirror.com
cnpm install -g @vue/cli
vue ui # 图形化界面中创建项目,安装router和vuex依赖,运行启动

2:component 目录下定义 KsdLoading 加载组件。

<template>
  <div class="loadingbox" v-if="closeFlag" @click="closeLoading">
    <div v-if="loadType == 2">{ { loadText[2] } }</div>
    <div v-if="loadType == 1">{ { loadText[1] } }</div>
    <div v-if="loadType == 0">{ { loadText[0] } }</div>
    <div v-if="loadType == 0">
      <div class="spinner2" :style='{"background": bgclor}' v-if="ctype == 2"></div>
      <div class="spinner" v-if="ctype == 1">
        <div class="spinner-container container1">
          <div class="circle1" :style='{"background": bgclor}'></div>
          <div class="circle2" :style='{"background": bgclor}'></div>
          <div class="circle3" :style='{"background": bgclor}'></div>
          <div class="circle4" :style='{"background": bgclor}'></div>
        </div>
        <div class="spinner-container container2">
          <div class="circle1" :style='{"background": bgclor}'></div>
          <div class="circle2" :style='{"background": bgclor}'></div>
          <div class="circle3" :style='{"background": bgclor}'></div>
          <div class="circle4" :style='{"background": bgclor}'></div>
        </div>
        <div class="spinner-container container3">
          <div class="circle1" :style='{"background": bgclor}'></div>
          <div class="circle2" :style='{"background": bgclor}'></div>
          <div class="circle3" :style='{"background": bgclor}'></div>
          <div class="circle4" :style='{"background": bgclor}'></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "KsdLoading",
  props: {
    ctype: {
      type: Number,
      default: 1
    },
    bgclor: {
      type: String,
      default: "#171915"
    },
    loadType: {
      type: Number,
      default: 0
    },
    loadText: {
      type: Array,
      default() {
        return ["数据加载中...", "数据加载完毕...", "亲,我是有底线的..."];
      }
    }
  },
  data() {
    return {
      closeFlag: true
    }
  },
  methods: {
    closeLoading() {
      this.closeFlag = false;
      this.$emit("message");
    }
  }
}
</script>
<style scoped>
/* loading样式 */
.loadingbox {
  text-align: center;
}
.spinner {
  margin: 20px auto;
  width: 20px;
  height: 20px;
  position: relative;
}
.container1 > div, .container2 > div, .container3 > div {
  width: 6px;
  height: 6px;
  background-color: #333;
  border-radius: 100%;
  position: absolute;
  -webkit-animation: bouncedelay 1.2s infinite ease-in-out;
  animation: bouncedelay 1.2s infinite ease-in-out;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.spinner .spinner-container {
  position: absolute;
  width: 100%;
  height: 100%;
}
.container2 {
  -webkit-transform: rotateZ(45deg);
  transform: rotateZ(45deg);
}
.container3 {
  -webkit-transform: rotateZ(90deg);
  transform: rotateZ(90deg);
}
.circle1 { top: 0; left: 0; }
.circle2 { top: 0; right: 0; }
.circle3 { right: 0; bottom: 0; }
.circle4 { left: 0; bottom: 0; }
.container2 .circle1 {
  -webkit-animation-delay: -1.1s;
  animation-delay: -1.1s;
}
.container3 .circle1 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}
.container1 .circle2 {
  -webkit-animation-delay: -0.9s;
  animation-delay: -0.9s;
}
.container2 .circle2 {
  -webkit-animation-delay: -0.8s;
  animation-delay: -0.8s;
}
.container3 .circle2 {
  -webkit-animation-delay: -0.7s;
  animation-delay: -0.7s;
}
.container1 .circle3 {
  -webkit-animation-delay: -0.6s;
  animation-delay: -0.6s;
}
.container2 .circle3 {
  -webkit-animation-delay: -0.5s;
  animation-delay: -0.5s;
}
.container3 .circle3 {
  -webkit-animation-delay: -0.4s;
  animation-delay: -0.4s;
}
.container1 .circle4 {
  -webkit-animation-delay: -0.3s;
  animation-delay: -0.3s;
}
.container2 .circle4 {
  -webkit-animation-delay: -0.2s;
  animation-delay: -0.2s;
}
.container3 .circle4 {
  -webkit-animation-delay: -0.1s;
  animation-delay: -0.1s;
}
@-webkit-keyframes bouncedelay {
  0%, 80%, 100% { -webkit-transform: scale(0.0) }
  40% { -webkit-transform: scale(1.0) }
}
@keyframes bouncedelay {
  0%, 80%, 100% {
    transform: scale(0.0);
    -webkit-transform: scale(0.0);
  } 40% {
      transform: scale(1.0);
      -webkit-transform: scale(1.0);
    }
}
.spinner2 {
  width: 24px;
  height: 24px;
  background-color: #67CF22;
  margin: 20px auto;
  -webkit-animation: rotateplane 1.2s infinite ease-in-out;
  animation: rotateplane 1.2s infinite ease-in-out;
}
@-webkit-keyframes rotateplane {
  0% { -webkit-transform: perspective(120px) }
  50% { -webkit-transform: perspective(120px) rotateY(180deg) }
  100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) }
}
@keyframes rotateplane {
  0% {
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
  } 50% {
      transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
      -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
    } 100% {
        transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
        -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
      }
}
</style>

3:定义 KsdPage 分页组件。

<template>
  <div>
    <ul class="ksd-paging">
      <!-- prev -->
      <li
          :class="[
          'paging-item',
          'paging-item--prev',
          { 'paging-item--disabled': index == 1 },
        ]"
          @click="prev"
      >
        上一页
      </li>
      <!-- first -->
      <li
          :class="[
          'paging-item',
          'paging-item--first',
          { 'paging-item--disabled': index == 1 },
        ]"
          @click="first"
      >
        首页
      </li>
      <li :class="['paging-item', 'paging-item--more']" v-if="showPrevMore">
        ...
      </li>
      <li
          :class="['paging-item', index == pager ? 'paging-item--current' : '']"
          v-for="pager in pagers"
          @click="go(pager)"
          :key="pager">
        { { pager } }
      </li>
      <li :class="['paging-item', 'paging-item--more']" v-if="showNextMore">
        ...
      </li>
      <!-- last -->
      <li
          :class="[
          'paging-item',
          'paging-item--last',
          { 'paging-item--disabled': index == pages },
        ]"
          @click="last"
      >
        尾页
      </li>
      <!-- next -->
      <li
          :class="[
          'paging-item',
          'paging-item--next',
          { 'paging-item--disabled': index == pages },
        ]"
          @click="next"
      >
        下一页
      </li>
      <li v-if="isGo" :class="['paging-item', 'paging-item--next']">
        <input class="pageinput" type="text" v-model="index"/>
      </li>
      <li v-if="isTotal" :class="['paging-item', 'paging-item--next']">
        共{ { total } }条
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  name: "KsdPage",
  props: {
    perPages: {
      type: Number,
      default: 5
    },
    pageIndex: {
      type: Number,
      default: 1
    },
    pageSize: {
      type: Number,
      default: 10
    },
    total: {
      type: Number,
      default: 1
    },
    isGo: {
      type: Boolean,
      default: false
    },
    isTotal: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    toPage() {
      this.go(this.index)
    },
    prev() {
      if (this.index > 1) {
        this.go(this.index - 1)
      }
    },
    next() {
      if (this.index < this.pages) {
        this.go(this.index + 1)
      }
    },
    first() {
      if (this.index !== 1) {
        this.go(1)
      }
    },
    last() {
      if (this.index != this.pages) {
        this.go(this.pages)
      }
    },
    go(page) {
      if (this.index !== page) {
        this.index = page
        this.$emit('change', this.index)
      }
    }
  },
  computed: {
    pages() {
      return Math.ceil(this.size / this.limit)
    },
    pagers() {
      const array = []
      const perPages = this.perPages * 1
      const pageCount = this.pages * 1
      let current = this.index * 1
      const _offset = (perPages - 1) / 2
      const offset = {
        start: current - _offset,
        end: current + _offset
      }
      if (offset.start < 1) {
        offset.end = offset.end + (1 - offset.start)
        offset.start = 1
      }
      if (offset.end > pageCount) {
        offset.start = offset.start - (offset.end - pageCount)
        offset.end = pageCount
      }
      if (offset.start < 1) offset.start = 1
      this.showPrevMore = (offset.start > 1)
      this.showNextMore = (offset.end < pageCount)
      for (let i = offset.start; i <= offset.end; i++) {
        array.push(i)
      }
      return array
    }
  },
  data() {
    return {
      index: this.pageIndex,
      limit: this.pageSize,
      size: this.total || 1,
      showPrevMore: false,
      showNextMore: false
    }
  },
  watch: {
    pageIndex(val) {
      this.index = val || 1
    },
    pageSize(val) {
      this.limit = val || 10
    },
    total(val) {
      this.size = val || 1
    }
  }
};
</script>
<style scoped>
/* 分页样式*/
.ksd-paging {
  display: inline-block;
  padding: 0;
  margin: 1rem 0;
  font-size: 0;
  list-style: none;
  user-select: none;
}
.ksd-paging .paging-item {
  display: inline;
  font-size: 14px;
  position: relative;
  padding: 6px 12px;
  line-height: 1.42857143;
  text-decoration: none;
  border: 1px solid #ccc;
  background-color: #fff;
  margin-left: -1px;
  cursor: pointer;
  color: #0275d8;
}
.ksd-paging .paging-item:first-child {
  margin-left: 0;
}
.ksd-paging .paging-item:hover {
  background-color: #f0f0f0;
  color: #0275d8;
}
.ksd-paging .paging-item.paging-item--disabled,
.ksd-paging .paging-item.paging-item--more {
  background-color: #fff;
  color: #505050;
}
.ksd-paging .paging-item.paging-item--disabled {
  cursor: not-allowed;
  opacity: .75;
}
.ksd-paging .paging-item.paging-item--more,
.ksd-paging .paging-item.paging-item--current {
  cursor: default;
}
.ksd-paging .paging-item.paging-item--current {
  background-color: #0275d8;
  color: #fff;
  position: relative;
  z-index: 1;
  border-color: #0275d8;
}
.ksd-paging .pageinput {
  width: 40px;
  text-align: center;
  outline: none;
  border: 1px solid #eee;
  color: #0275d8;
}
</style>

4:router/index.js 中定义路由。

{
  path: '/userList',
  name: 'UserList',
  component: () => import('../views/UserList.vue')
}

5:App.vue 中定义路由导航。

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/userList">用户列表</router-link>
  </div>
  <router-view/>
</template>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  padding: 30px;
}
#nav a {
  font-weight: bold;
  color: #2c3e50;
}
#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

6:相应页面中注册和使用组件。

<template>
  <div class="userList">
    <h1>我是用户列表</h1>
    <p v-for="(user, index) in users" :key="user.id">
      <span>{ {index} }:{ {user.id} } == { {user.name} }</span>
    </p>
    <ksd-loading @message="loadingChange"></ksd-loading>
    <ksd-page :total="total" @change="pageChange"></ksd-page>
  </div>
</template>
<script>
import KsdLoading from "@/components/KsdLoading";
import KsdPage from "@/components/KsdPage";
export default {
  name: "UserList",
  components: {
    KsdLoading, KsdPage
  },
  data() {
    return {
      users: [],
      total: 110
    }
  },
  created() {
    this.users = [
      { id: 1, name: "zhangsan1" },
      { id: 2, name: "zhangsan2" },
      { id: 3, name: "zhangsan3" }
    ]
  },
  methods: {
    loadingChange() {
      alert("关闭了...");
    },
    pageChange(pageNo) {
      alert(pageNo);
    }
  }
}
</script>
<style scoped>
</style>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
  <ksd-loading></ksd-loading>
</template>
<script>
import KsdLoading from "@/components/KsdLoading";
export default {
  name: "About",
  components: {
    KsdLoading
  },
  data() {
    return {
      users: []
    }
  },
  created() {
    this.users = [
      { id: 1, name: "zhangsan1" },
      { id: 2, name: "zhangsan2" },
      { id: 3, name: "zhangsan3" }
    ]
  }
}
</script>
<style scoped>
</style>

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

what's your name.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值