美文网首页Web前端之路优美编程WEB前端程序开发
当你自己封装Vue组件库时会用到的知识点

当你自己封装Vue组件库时会用到的知识点

作者: 小遁哥 | 来源:发表于2019-08-11 18:39 被阅读2次

    源码在 https://github.com/xiaodun/sf-feed

    函数式组件

    <TagConvert tag="span" age="9" sex="man">12312</TagConvert>
    

    生成的DOM如下

    <span age="9" sex="man">12312</span>
    

    内部实现是这样的,用到自定义组件上,意义就大了

    
    <script>
    export default {
      functional: true,
      name: "TagConvert_vue",
      props: {
        tag: {
          type: String,
          default: "div"
        }
      },
      render(createElement, context) {
        return createElement(context.props.tag, context.data, context.children);
      }
    };
    </script>
    

    v-bind="$attrs"

    批量绑定父组件传递过来的属性
    看一下iview官网上,表单验证的模板代码

    handleSubmit(name) {
          this.$refs[name].validate((valid) => {
                        if (valid) {
                            this.$Message.success('Success!');
                        } else {
                            this.$Message.error('Fail!');
                        }
                    })
                }
    

    name 对应的是<Form ref="formInline">
    现在我想封装一个专门用来提交的<Submit> 组件,只有在验证成功的时候触发回调

    <Submit @submit="onSubmit">
        <Button 
            width="100%"
              :status="submitStatus"
            class="login-btn"
            height="36px"
         >{{$t('login')}}</Button>
    </Submit>
    

    上述这样会多一层无用的DOM嵌套,我希望是这样的

     <Submit
         width="100%"
         :status="submitStatus"
         class="login-btn"
         height="36px"
         @submit="onSubmit"
        >{{$t('login')}}</Submit>
    

    <Submit> 内部实现结合了<TagConvert>v-bind="$attrs"

    <template>
    
      <TagConvert
        v-if="tag[0].charCodeAt(0)<=90"
        :tag="tag"
        v-bind="$attrs"
        @click.native="onSubmit"
      >
        <slot></slot>
      </TagConvert>
      <!-- 原生组件 -->
      <TagConvert
        v-else
        :tag="tag"
        v-bind="$attrs"
        @click="onSubmit"
      >
        <slot></slot>
      </TagConvert>
    
    </template>
    
    <script>
    import { findParentComponent } from "../../find";
    export default {
      name: "Submit_vue",
      props: {
        tag: {
          type: String,
          default: "Button"
        }
      },
      methods: {
        onSubmit($event) {
          $event.preventDefault();
          //查找
          let validInfo = this.submitComponent.onValidator();
          if (validInfo.status) {
            this.$emit("submit", validInfo.passValues);
          }
        }
      },
      mounted() {
        let findInfo = findParentComponent(this, "FormItem");
        if (!findInfo.status) {
          findInfo = findParentComponent(this, "Form");
        }
        if (findInfo.status) {
          this.submitComponent = findInfo.component;
        } else {
          console.error("没有找到Form或FormItem");
        }
      }
    };
    </script>
    

    findParentComponent 是基于Vue自身节点构造,可以通过$parent追溯父元素,$children遍历子元素

    provide 与 inject

    这种适合<Form><FormItem>这种父子组件
    <Form>

    export default {
      name: "Form_vue",
      props: {
        labelWidth: String
      },
      provide() {
        return {
          Form: this
        };
      }
    }
    

    <FormItem>

    export default {
      name: "FormItem_vue",
      inject: ["Form"],
    }
    

    <FormItem> 可以 this.Form 访问
    如果<FormItem> 没有得到<Form>的引用会报错哦

    动态挂载HTML

    render 的动态再需要通过JS触发时,是乏力的,比如一个类似于iview 的<Notice>组件,需要如下手段

    import Notification from "./Notification";
    import Vue from 'vue';
    
    const NotificationInstance = (() => {
        let instance = new Vue({
            render(createElement) {
                return createElement(Notification)
            }
        })
        const component = instance.$mount();
        document.body.appendChild(component.$el);
        const notification = instance.$children[0];
        return notification;
    })();
    Vue.prototype.$Notice = {
        show(argOptions) {
            NotificationInstance.add(argOptions);
        }
    }
    
    

    可以this.$Notice.show来触发

    上述可发现,React可以做到的,Vue也可以做到,可有千秋。

    但是Vue更贴近开发者和业务场景,React的抽象层次更高,具体的落实需要开发者去做,更适合研究琢磨,这么看来,React会走的更远。

    人生苦短,我用Vue。

    相关文章

      网友评论

        本文标题:当你自己封装Vue组件库时会用到的知识点

        本文链接:https://www.haomeiwen.com/subject/fpesjctx.html