美文网首页
vue.js 组件知识总结

vue.js 组件知识总结

作者: 彤_姑娘 | 来源:发表于2018-01-11 00:22 被阅读68次

    组件局部注册

    <div id="app">
            hello vue
            <my-component></my-component>   
        </div>
        <script>
            var Child = {
                template:'<div>局部注册组件</div>'
            };
            new Vue({
                el:'#app',
                components:{
                    'my-component':Child
                }
            })
        </script>
    

    is 属性挂载组件

    常见:ul、select、table
    (字符串模板除外:.vue文件)

    例:在table里使用组件无效,添加一个is属性。在is下往下写无效。

    <div id="app">
            <table border="1">
                <tbody is="my-com"></tbody>
            </table>
        </div>
        <script>
           Vue.component('my-com',{
             template:'<tr><td>1</td><td>2</td></tr>'
           });
    
            new Vue({
                el:'#app'
            })
        </script>
    

    props

    数组和对象是引用类型,指向同一片内存空间,所以props是数组和对象时,修改子组件内容会影响到父组件。默认双向绑定。

    数据验证

    Vue.component('my-component',{
            props:{
                propA:Number, //必须是数字类型
                propB:[String,Number],
                propC:{//布尔值,如果没定义,默认是true
                    type:Boolean,
                    default:true
                },
                propD:{//数字,而且是必传
                    type:Number,
                    required:true
                },
                propE:{//如果是数组或对象,默认值必须是一个函数来返回
                    type:Array,
                    default:function (){
                        return [];
                    }
                },
                propF:{//自定义一个验证函数
                    validator:function(value){
                        return value > 10;
                    }
                }
            } 
        })
    

    自定义事件

    v-on 监听自定义事件外,也监听DOM事件。用.native 修饰符表示监听的是一个原生事件,监听的是该组件的根元素。

    <my-component v-on:click.native="handleClick"></my-component>
    

    使用 v-model

    • 接受一个value属性;
    • 在有新的value时触发input事件
      <div id="app">
            {{ value }}
            <my-com v-model="value" @click="minus"></my-com>
            <!-- 父向子:执行减操作 -->
            <button @click="minus">-1</button>
        </div>
        <script>
        // 点击add加一 把const++通过input事件把const传递出去
        Vue.component('my-com', {
            props: {
                // 这个必须叫value,并与input一一对应。不懂为啥?
                value: {
                    type: Number
                }
            },
            template: '<div> {{ const1 }} <button @click="add">+1</button></div>',
            data() {
                return {
                    const1: this.value
                }
            },
            methods: {
                add() {
                    this.const1++;
                    this.$emit('input', this.const1);   //必须为input
                }
            },
            watch:{
                value(val){
                    this.const1 = val;
                }
            }
        });
        new Vue({
            el: '#app',
    
            data: {
                value: 1
            },
            methods: {
                minus() {
                    this.value--;
                },
            }
    
        })
        </script>
    

    非父子组件通信

    推荐使用一个空 Vue 实例作为中央事件总线(bus),也就是一个中介。

    <div id="app">
            {{ message }}
            <my-coma></my-coma> 
        </div>
        <script>
         // 创建空的bus实例 
        const bus = new Vue({
            //可以继续扩展bus
            //data,methods...
        });
         // 注册一个组件
        Vue.component('my-coma',{
            template:'<button @click="passEvent">click</button>',
            methods:{
                passEvent(){
                    bus.$emit('msgInfo','come from children ');
                }
            }
        });
        new Vue({
            el:'#app',
            data:{
                message:''
            },
            mounted(){
                bus.$on('msgInfo',(msg)=>{
                    this.message = msg;
                })
            }
        })
        </script>
    
    非父子组件通信--父链、子链

    this.$parent 可以在子组件中取到父组件的东西

    this.$children 可以拿到app 实例里的所有子组件,如果有很多子组件,可以得到一个数组。

    修改父(子)组件内容,最好不这么做!

    非父子组件通--子组件索引

    子组件索引只在组件渲染完成后填充,非响应式的,仅作为直接访问子组件的应急方案,应当避免在模板、计算属性中使用自定义子组件索引。

    加载两个相同的组件,用ref 区分,如果需要for循环,可以动态绑定:ref="a"

    <my-coma ref='a'></my-coma> 
    <my-coma ref='b'></my-coma> 
    

    取值:

    this.$refs.a
    

    slot 内容分发

    当需要让组件组合使用时,要内容分发,混合父组件内容和子组件模板就叫内容分发。

    <div id="app">
           <my-com>
               <!-- message生命周期由父组件或父实例来决定的,包括作用域,和my-com本身没关系。 -->
               {{ message }}
           </my-com>
       </div>
       <script>
           //hello world:
           // hello来自‘my-com’组件本身的内容,
           // world:父组件通过<slot>来充当的这部分内容
           Vue.component( 'my-com',{
               //slot 标签挂载内容,
               template:'<div>hello <slot></slot></div>',
    
           });
    
           new Vue({
               el:'#app',
               data:{
                   message:'world'
               }
           })
       </script>
    

    具名slot
    在一个组件里,设置多个slot来区分显示的内容。(按照slot顺序展示:你好 朋友)

    <my-com>
        <div slot="a">
            你好
        </div>
        <div slot="b">
            朋友
        </div>
    </my-com>
    

    script

    <script>
            Vue.component( 'my-com',{
                template:'<div>hello <slot name="a"></slot><slot name="b"></slot></div>',
    
            });
            new Vue({
                el:'#app',
            })
        </script>
    

    slot展示默认内容
    如果组件里没有内容,就会显示slot里的默认内容。内容作用域只与当前组件(my-com)相关,与父组件无关。

    <div id="app">
            <my-com></my-com>
        </div>
    

    script

    Vue.component( 'my-com',{
                template:'<div>hello <slot>这里是默认</slot></div>',
            });
    

    访问slot
    rander函数用的多

    mounted(){
        this.$slots.default   //取默认内容
        this.$slots.a         //取a的内容
    }
    

    组件的高级用法

    递归组件

    满足条件:

    1. 必须给组件设置一个name。
    2. 在一个合适的时间结束组件的递归,否则报超栈的错误。
    <div id="app">
            <my-com :count="1"></my-com>
        </div>
        <script>
            Vue.component('my-com',{
                name:'myCon',
                props:{
                    count:{
                        type:Number,
                        default:1
                    }
                },
                template:'<div><my-com :count="count +1" v-if="count<3"></my-com>{{ count }}</div>',
            });
            new Vue({
                el:'#app',
            })
        </script>
    

    内联模板(少用)

    给组件标签使用inline-template特性,组件就会把它的内容当做模板,而不是当做内容分发。会替代子组件的template来显示。

    <div id="app">
        <my-com inline-template>
            <div>
                {{message}}
            </div>
        </my-com>
    </div>
    

    script

    结果为:你好

    <script>
            Vue.component( 'my-com',{
                // template:'<div>hello <slot>这里是默认内容</slot></div>',
                data(){
                    return{
                        message:'你好'
                    }
                }
            });
            new Vue({
                el:'#app',
                data:{
                    message:'world'
                },
            })
        </script>
    

    {{message}}作用域为组件内的data,有些难理解,少用吧~

    异步组件

    组件比较庞大时,使用异步组件

    1. 按需加载,可以节省首次加载的时间,提高速度,也算是一个性能优化。
    2. 那么一个组件可能会被使用多次,按需加载的话也不会加载多次,第一次加载完成就会缓存下来,和webpack是一样的,所以不用担心
        <div id="app">
            <my-com :count="1"></my-com>
        </div>
        <script>
            Vue.component('my-com',function(resolve,reject){
                window.setTimeout(function(){
                    resolve({
                        template:'<div>from 异步加载组件</div>'
                    })
                },3000)
            });
            new Vue({
                el:'#app',
            })
        </script>
    

    $nextTick

    等组件渲染完后使用

      this.$nextTick( () => {
          
      });
    

    vue 如何观察数据变化?
    并不是直接更新DOM,而是开启一个检查队列,缓存在一次事件循环中,缓存中会排除重复数据来避免不必要计算或DOM的操作,在下一次循环tick中,vue才会刷新队列,执行实际的操作。如果使用for循环动态改变100次数据,实际上只触发1次

    检测:

    vue 优先使用promise检测,不支持会使用HTML5新特性 Mutation Observer 的方法,都不支持采用setTimeout

    x-template

    前提是你没有使用webpack

     <div id="app">
        <my-com></my-com>
        <script type="text/x-template" id="my">
            <div>...</div>
        </script>  
    </div>
    

    手动挂载实例

    一般使用 new vue 创建实例

    new Vue({ 
        el:'#app'
    })
    

    在特殊情况下也可以动态创建 vue 实例。

    vue提供两个API:

    extend : 基础vue 构造器,创建了一个子类。参数包含组件选项的对象

    $mount :挂载 (有很多参数,参见官网)

        <div id="app">
            hello Vue
        </div>
        <script>
        // 用extend 定义组件内容
            const myComponent = Vue.extend({
                template:'<div> from extend </div>' 
            });
        //通过 $mount 手动挂载在指定DOM里(通过工厂函数方法),支持class和id选择器
            new myComponent().$mount('#app');
        </script>
    

    结果:from extend 覆盖 hello vue

    问答模块

    1.watch 与 computed 区别

    watch:单纯监听某些东西变化,执行一些操作。

    computed:根据已有的 data 或 props 的改变,来动态输出一个内容.常见的:排序、过滤、千位运算符等计算属性。

    2.bus 怎么避免全局污染?

    在 webpack 中,bus是一个bus.js文件,通过模块化就不会全局污染。

    import bus from './bus.js'
    
    3.mixins混合

    把部分vue的配置merge到实例里,如:data、methods、props、计算属性、生命周期等内容,形成复用。

    mixins:[]
    

    组件解决UI的复用,mixins混合解决组件内部配置的复用

    4.远程搜索(需要补充)

    数据过多不建议使用select数据下拉。

    5.keep-alive (需要补充)

    让组件做缓存

    文章内容参考:
    Vue.js 实战之组件篇:https://segmentfault.com/l/1500000009448056/play
    说说Vue的异步组件:https://juejin.im/entry/599562f36fb9a0249716d299
    vue.js官网:https://cn.vuejs.org/v2/guide/components.html

    相关文章

      网友评论

          本文标题:vue.js 组件知识总结

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