1--组件

    可以理解为页面的一部分,其具有独立的逻辑及功能或界面,同时又能与其他部分进行相应地融合,变成完整的应用。页面可以由这样一个个的组件构成,如导航栏、列表项、弹窗、侧边栏、下拉框、多选框等。页面相当于一个大的框架,将这些组件组合成一个功能更为强大的模块,组件方便被替换或删除,而不影响整个应用程序的运行。

 

前端组件化的思想:

将大的东西拆成一个个的小东西,然后完成小东西的功能,最后再将这些小东西进行组合,得到最初想要的模样,即分而治之的思想。

 

使用组件的优势:

提高开发效率;可重用;简化调试步骤;便于协同开发;提升整个项目的可维护性。

 

2—vue中的组件

   Vue中的组件是一个自定义标签,vue.js的编辑器为其添加特殊功能;vue也可以扩展原生的html元素,封装可重用的代码。

   组件的基本组成:样式结构、行为逻辑、数据

如下为单文件组件,包含了样式结构、行为逻辑、数据。

  

antdesign vue日期控件展示月份 vue 日期范围组件_Vue

 

3—注册组件

  全局注册:

  可以在任何模板中使用,使用前先注册。

  语法:使用Vue.component(组件名,选项对象)

  其中,Vue是构造函数,component是其下的方法

  组件名命名规则:camelCase、kebab-case

  在html中使用组件:使用kebab-case命名法

  eg. 注册:Vue.component(’my-component’,{})

     使用:<my-component></my-component>

  局部注册:

    在组件实例中通过选项对象注册,只在所注册的作用域中使用

{ 
components:{

    组件名:选项对象
 }
}

 

4--组件间通信:

父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。

 

父组件->子组件:

组件实例的作用域是孤立的,不能在子组件直接用父组件的数据。

父组件向子组件传递数据时,可以在组件上使用自定义属性绑定数据,在组件中需要显示的用props声明自定义属性。

 

子组件->父组件:

子组件向父组件传递数据时,需要用到自定义事件,父组件用$on监听自定义事件,$emit触发父组件所关心的自定义事件。父组件用v-on用来监听子组件的事件是否触发了来作出相应的处理。

组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <style>
    </style>
</head>

<body>
    <div id="app" class="common">
        <my-component :my-name="name" :my-age="age"></my-component>
    </div>
    <template id="myComponent">
        <div>
            子组件数据:
            <p>name:{{myName}}</p>
            <p>name:{{myAge}}</p>
        </div>
    </template>
    <script>
        new Vue({
            el:'#app',
            data:{
                name:'kkkk',
                age:20
            },
            components: {
                'my-component':{
                    template:'#myComponent',
                    props:['myName','myAge']
                }
            }
        })
    
    </script>
</body>

</html>

在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。
例如,在prop中定义的myName,在用作特性时需要转换为my-name


父组件访问子组件:使用$children或$refs
子组件访问父组件:使用$parent
子组件访问根组件:使用$root

$children示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <style>
    </style>
</head>
<body>
    <div id="app">
        <parent-component></parent-component>    
    </div>
    <template id="parent-component">
        <div>
           <child-component1></child-component1>
            <child-component2></child-component2>
            <button @click="showChildComponentData">显示子组件数据</button>  
        </div>  
    </template>
    <template id="child-component1">
        <h2>child-component1 data: {{msg}}</h2>
    </template>
    <template id="child-component2">
         <h2>child-component2 data: {{msg}}</h2>
    </template>
    <script>
        Vue.component('parent-component', {
            template:'#parent-component',
            components: {
                'child-component1':{
                    template:'#child-component1',
                    data:function(){
                        return {
                            msg: 'child-component1'
                        }
                    }
                },
                'child-component2':{
                    template:'#child-component2',
                    data:function(){
                        return {
                            msg: 'child-component2'
                        }
                    }
                }
            },
            methods: {
                // 在父组件中,通过this.$children可以访问子组件。
                // this.$children是一个数组,它包含所有子组件的实例。
                showChildComponentData: function(){
                    for(var i= 0; i < this.$children.length; i++) {
                        (this.$children[i].msg)
                    }
                }
            }
        })
        new Vue({
            el:'#app',
        })
    
    </script>
</body>

</html>


$refs示例:
    
组件个数较多时,在子组件上使用v-ref指令,可以给子组件指定一个索引ID
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:
$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <style>
    </style>
</head>

<body>
    <div id="app" class="common">
        <parent-component></parent-component>    
    </div>

    <template id="parent-component">
         <div>
            <child-component1 ref="comp1"></child-component1>
            <child-component2 ref="comp2"></child-component2>
            <button @click="showChildComponentDataRef">显示子组件数据ref</button>  
         </div>
    </template>
    <template id="child-component1">
        <h2>child-component1 data {{msg}}</h2>
    </template>
    <template id="child-component2">
         <h2>child-component2 data {{msg}}</h2>
    </template>
    <script>
        Vue.component('parent-component', {
            template:'#parent-component',
            components: {
                'child-component1':{
                    template:'#child-component1',
                    data:function(){
                        return {
                            msg: 'child-component1'
                        }
                    }
                },
                'child-component2':{
                    template:'#child-component2',
                    data:function(){
                        return {
                            msg: 'child-component2'
                        }
                    }
                }
            },
            methods: {
                showChildComponentDataRef: function() {
                    console.log(this.$refs,'refs')
                    alert(this.$refs.comp1.msg);
                    alert(this.$refs.comp2.msg);
                }
            }
        })
        new Vue({
            el:'#app',
        })
    </script>
</body>

</html>



在子组件中,通过this.$parent可以访问到父组件的实例,推荐 -只有组件自己能修改它的状态
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <style>
    </style>
</head>

<body>
    <div id="app">
        <parent-component></parent-component>    
    </div>

    <template id="parent-component">
         <div>
            <child-component></child-component>
         </div>
    </template>
    <template id="child-component">
        <div>
            <h2>child-component</h2>
            <button @click="showChildComponentDataParent">显示父组件数据</button>  
        </div>
    
    </template>

    <script>
        Vue.component('parent-component', {
            template:'#parent-component',
            components:{
                'child-component':{
                    template:'#child-component',
                    methods: {
                        showChildComponentDataParent() {
                            // 尽管可以访问父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽量显式地使用 props 传递数据
                            // 推荐:只有组件自己能修改它的状态
                            console.log(this.$parent)
                            alert(this.$parent.msg)
                        }
                    }
                }
            },
            data:function(){
                return {
                    msg:'i am parent component data'
                }
            }    
            })
        new Vue({
            el:'#app',
        })
    
    </script>
</body>

</html>


自定义事件:

有时候我们希望触发父组件的某个事件时,可以通知到子组件;触发子组件的某个事件时,可以通知到父组件。
Vue 实例实现了一个自定义事件接口,用于在组件树中通信。这个事件系统独立于原生 DOM 事件,用法也不同。
// 每个vue实例都是一个事件触发器:使用$on()监听事件;使用$emit()在它上面派发事件;使用$dispatch()派发事件,事件沿着父链冒泡;使用$broadcast()广播事件,事件向下传导给所有的后代

// ps $dispatch()  $broadcast()  已弃用




vue.js 组件的api来源于:prop slot  事件

prop允许外部环境传递数据给组件
事件允许组件触发外部环境的action
slot允许外部环境插入内容到组件的视图结构内

  

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <style>
        .red{
            background: skyblue;
        }
    </style>
</head>

<body>
    <div id="app" class="common">
        <my-component></my-component>
    </div>
    // 二者等价
    <template id="myComponent">
        <div>This is a component1!</div>
    </template>
    <-- <script type="text/x-template" id="myComponent">
        <div>This is a component2!</div>
    </script> -->
    <script>
        // Vue.component()的第1个参数是标签名称,第2个参数是一个选项对象,使用选项对象的template属性定义组件模板
       Vue.component('my-component', {
        // 模板id
           template:`#myComponent`
       })

        new Vue({
            el:'#app'
        })
    
    </script>
</body>

</html>

template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译。如果使用<template>标签,则不需要指定type属性。
使用<script>标签时,type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略<script>标签内定义的内容。

ps:二者等价,选其一就可以了
    <template id="myComponent">
        <div>This is a component1!</div>
    </template>
    与
       <script type="text/x-template" id="myComponent">
        <div>This is a component2!</div>
    </script>

  

5—组件中的data必须是函数

   每个组件是相互独立的,如果它们共用一个对象,在更改一个组件数据的时候,会影响其他组件。如果是函数的话,每个组件都会有自己独立的数据,相互之间不会影响。

 

6—受限制的元素

   DOM模板解析:vue是在浏览器解析和标准化html后才获取模板内容,所以有些元素限制了能被它包裹的元素。如ul里只能放li

   某些元素中放入了自定义属性,不符合W3C标准,会解析错误。变通的方式:使用特殊属性is来扩展HTML标签功能。

 

7-单向数据流

   数据从父组件流向(传递)子组件,只能单向绑定。在子组件内部不应该修改父组件传递过来的数据。

改变prop的情况:

 作为data中局部数据的初始值使用;作为子组件中的computed属性。

 

8-props验证

  组件可以为props指定验证要求,如果未指定验证要求,vue会发出警告。

Props:{

  propA:Number,  //指定类型

  propB:[String,Number],//多种类型

  propC:[type:String,required:true], //必传,且为字符串

  propD:[type:Number,default:100],//数字类型,默认100

  propE:{type:Number,default:function(){

   return 1000

}},

//自定义验证规则

propF:{validator:function(value){return value>10}}

}

   

9-使用slot分发内容

  使用一种方式混合父组件的的内容与子组件自己的模板,这个过程被称为内容分发。在子组件中使用特殊的<slot>元素作为内容的插槽。这样可使组件的可扩展性更强。

单个slot:

  在子组件模板中有slot标签,被视为备用内容,在父组件不提供内容的情况下使用,如果父组件提供内容,则把整个内容片段插入到slot所在的dom位置,并替换掉slot标签本身。

子组件模板中没有slot标签,父组件提供的内容会被抛弃。
<div id="app"> 
    <h2>自定义组件</h2> 
    <custom> 
        <!--当写在自定义标签之间的内容,要混合子组件中的模板--> 
        <div>我是html结构</div> 
    </custom> 
</div> 
<script> 
    //定制模板div 
    Vue.component("custom",{ 
        template:` 
         <div> 
            <slot>//该标签内的内容将会被我是html结构覆盖掉 
            <p>这是第1个提醒</p> 
            <p>这是第2个提醒</p> 
            <p>这是第3个提醒</p> 
            </slot> 
         </div> 
        ` 
    }) 
    new Vue({ 
        el:"#app" 
    }); 
</script>

  

<body> 
<div id="app"> 
    <h2>自定义组件</h2> 
    <custom> 
        <!--当写在自定义标签之间的内容,要混合子组件中的模板--> 
        <div>替换第1个提醒</div> 
        <div>替换第2个提醒</div> 
        <div>替换第3个提醒</div> 
    </custom> 
</div> 
<script> 
    //定制模板div 
    Vue.component("custom",{ 
        template:` 
         <div> 
            <slot> 
            <p>这是第1个提醒</p> 
            <p>这是第2个提醒</p> 
            <p>这是第3个提醒</p> 
            </slot> 
         </div> 
        ` 
    }) 
    new Vue({ 
        el:"#app" 
    }); 
</script> 
</body>

  

具名slot:

  <slot>元素可以用一个特殊的属性name来配置如何分发内容。

可以使用一个匿名的slot,处理那些没有对应slot的内容
<div id="app"> 
    <h2>自定义组件</h2> 
    <custom> 
        <!--当写在自定义标签之间的内容,要混合子组件中的模板--> 
        <div slot="one">替换第1个提醒</div> 
        <div slot="three">替换第3个提醒</div> 
        <template slot="two"> 
            <div>替换第2个提醒</div> 
            <span>替换第2个提醒</span> 
            <div>替换第2个提醒</div> 
        </template> 
    </custom> 
</div> 
<script> 
    //定制模板div 
    Vue.component("custom",{ 
        template:` 
         <div> 
         <slot name="one"><p>这是第1个提醒</p></slot> 
         <slot name="two"><p>这是第2个提醒</p></slot> 
         <slot name="three"><p>这是第3个提醒</p></slot> 
         </div> 
        ` 
    }) 
    new Vue({ 
        el:"#app" 
    }); 
</script>

 

编译作用域:

  父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

<!DOCTYPE html> 
<html> 
<head lang="en"> 
    <meta charset="UTF-8"> 
    <title></title> 
    <script src="vue.js"></script> 
</head> 
<body> 
<div id="app"> 
    <custom>  <!--这里渲染的数据是父组件中的数据--> 
        {{message}} 
    </custom> 
</div> 
<script> 
    Vue.component("custom",{  //子组件 
        data(){ 
          return { 
              message:"我是子组件的数据" 
          } 
    }, 
    template:` 
       <div> 
          {{message}}  <!--这里是渲染子组件里的数据--> 
            <p>我是第1个提醒</p> 
            <slot></slot> 
       </div> 
    ` 
    }) 
    new Vue({   //父组件 
        el:"#app", 
        data:{ 
            message:"我是父组件的数据" 
        } 
    }); 
</script> 
</body> 
</html>

 

10. 获取url中参数:

  通过路由跳转的页面交互,可通过this.$route.query或this.$route.params获取url中地址参数

 

 

  

ps:看的东西有点杂,且是之前的word笔记后更新到博客,除了官网,想不起来具体参考哪些了各路大神了,如有雷同,欢迎指出。

宝剑锋从磨砺出,梅花香自苦寒来。