# Vue 指南

# 注册组件

# 全局注册

Vue.component('component-a', {
    /* ... */
})
Vue.component('component-b', {
    /* ... */
})
Vue.component('component-c', {
    /* ... */
})

new Vue({
    el: '#app'
})
<div id="app">
    <component-a></component-a>
    <component-b></component-b>
    <component-c></component-c>
</div>

# 局部注册

import ComponentA from './ComponentA.vue'

export default {
    components: {
        ComponentA
    },
    // ...
}

# 动态&异步加载组件

<template>
  <div id="app">
    <img @click="addMod" alt="Vue logo" src="./assets/logo.png" width="25%" />
    <component v-bind:is="currentTabComponent"></component>
  </div>
</template>

<script>
import Loading from "./components/Loading";
import Err from "./components/Err";
export default {
  name: "App",
  data() {
    return {
      currentTabComponent: "",
    };
  },
  methods: {
    addMod() {
      console.log(this);
      if (this.currentTabComponent) {
        alert("onready");
      } else {
        this.currentTabComponent = () => ({
          // 需要加载的组件。应当是一个 Promise
          component: import("./components/Demo"),
          // 加载中应当渲染的组件
          loading: Loading,
          // 出错时渲染的组件
          error: Err,
          // 渲染加载中组件前的等待时间。默认:200ms。
          delay: 200,
          // 最长等待时间。超出此时间则渲染错误组件。默认:Infinity
          timeout: 3000,
        });
      }
    },
  },
};
</script>

# 写个插件?如何调用?

MyPlugin.install = function(Vue, options) {
    // 1. 添加全局方法或 property
    Vue.myGlobalMethod = function() {
        // 逻辑...
    }

    // 2. 添加全局资源
    Vue.directive('my-directive', {
        bind(el, binding, vnode, oldVnode) {
            // 逻辑...
        }
        ...
    })

    // 3. 注入组件选项
    Vue.mixin({
        created: function() {
                // 逻辑...
            }
            ...
    })

    // 4. 添加实例方法
    Vue.prototype.$myMethod = function(methodOptions) {
        // 逻辑...
    }
}

main.js中调用

import MyPlugin from "./plugin/MyPlugin";
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

new Vue({
    // ...组件选项
})

# 如何写个自己的UI组件库?

# Button初体验

目录结构

Button.vue

<template>
  <button
    class="my-buttom my-button--normal"
    :class="[
      type ? `my-button--${type}` : '',
      {
        'my-button--round': round,
        'my-button--disabled': disabled,
      },
    ]"
    @click="handleClick"
  >
    <slot></slot>
  </button>
</template>

<script>
export default {
  name: "Button",
  props: {
    type: {
      type: String,
      default: "default",
    },
    round: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    handleClick(evt) {
      this.$emit("click", evt);
    },
  },
};
</script>

index.js

import Buttom from "./Button.vue";

/* istanbul ignore next */
Buttom.install = function(Vue) {
    Vue.component(Buttom.name, Buttom);
};

export default Buttom;

main.js 中调用

import Vue from "vue";
import App from "./App.vue";
import Buttom from "./plugin/Button";

Vue.use(Buttom);
Vue.config.productionTip = false;

new Vue({
    render: (h) => h(App)
}).$mount("#app");

App.vue 中使用,测试一下

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" width="25%" />
    <HelloWorld msg="Hello Vue in CodeSandbox!" />

    <div class="test-btn">
      <Button round type="primary">主要按钮</Button>
      <Button disabled type="info">信息按钮</Button>
      <Button type="default">普通按钮</Button>
      <Button disabled round type="warning">警告按钮</Button>
      <Button type="danger">危险按钮</Button>
    </div>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld";
export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

看看效果

# 全局组件不一样的调用方法?Dialog (函数式组件)

目录结构

Dialog.vue

 <template>
  <div class="my-dialog-wrap" v-if="isShow">
    <div class="my-dialog-mask" v-if="!maskHide"></div>
    <div class="my-dialog">
      <h4 class="my-dialog-title">{{ title }}</h4>
      <div class="my-dialog-content">
        <slot>{{ content }}</slot>
      </div>
      <div class="my-dialog-btn">
        <button
          @click="cancel"
          class="my-dialog--cancel"
          v-if="isShowCancelBtn"
        >
          {{ cancelVal }}
        </button>
        <button @click="confirm" class="my-dialog--confirm">
          {{ confirmVal }}
        </button>
      </div>
    </div>

  </div>
</template>

<script>
export default {
  name: "Dialog", 
  props: {

    title: {
      type: String,
      default: "标题",
    },
    content: {
      type: String,
      default: "这是内容",
    },
    confirmVal: {
      type: String,
      default: "确定",
    },
    cancelVal: {
      type: String,
      default: "取消",
    },
    maskHide: {
      type: Boolean,
      default: false,
    },
    isShowCancelBtn: {
      type: Boolean,
      default: true,
    },

  }, 
  data() {

    return {
      isShow: false,
    };

  }, 
  methods: {

    show() {
      this.isShow = true;
    },
    hide() {
      this.isShow = false;
    },
    confirm() {
      this.isShow = false;
      console.log("confirm");
    },
    cancel() {
      this.isShow = false;
      console.log("cancel");
    },

  }, 
}; 
</script>

index.js

import Dialog from "./Dialog.vue";

/* istanbul ignore next */
Dialog.install = function(Vue) {
    Vue.component(Dialog.name, Dialog);
    // 1. 创建组件构造器
    const dialogContrustor = Vue.extend(Dialog);

    // 2. new  组件实例
    const dialog = new dialogContrustor();

    // 3. 获取el
    const el = dialog.$mount().$el;

    // 4. 添加到document.body
    document.body.appendChild(el);

    // 5. 添加到原型链上
    Vue.prototype.$dialog = dialog;
};

export default Dialog;

main.js 中引用

import Vue from "vue";
import App from "./App.vue";
import Buttom from "./plugin/Button";
import Dialog from "./plugin/Dialog";

Vue.use(Buttom);
Vue.use(Dialog);
Vue.config.productionTip = false;

new Vue({
    render: (h) => h(App)
}).$mount("#app");

App.vue 中使用,测试一下

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" width="25%" />
    <HelloWorld msg="Hello Vue in CodeSandbox!" />

    <div class="test-btn">
      <Button round type="primary">主要按钮</Button>
      <Button disabled type="info">信息按钮</Button>
      <Button type="default">普通按钮</Button>
      <Button disabled round type="warning">警告按钮</Button>
      <Button @click="clickMe" type="danger">危险按钮</Button>
    </div>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld";
export default {
  name: "App",
  components: {
    HelloWorld,
  },
  methods: {
    clickMe() {
      this.$dialog.show();
    },
  },
};
</script>

看看效果

# CodeSandbox

Last Updated: 8/5/2021, 11:55:32 PM