1. 组件介绍

组件(component),vue.js最强大的功能之一

  • 作用:封装可重用的代码,通常一个组件就是一个功能体,便于在多个地方都能调用该功能体
  • 根组件我们实例化的Vue对象就是一个组件,且是所有组件的根组件
  • 分类:全局组件,局部组件
  • 不足:跳转时,无法传递参数,则无法实现同一个页面根据不同的参数显示不同内容

注:每个组件都是Vue的实例对象

2. 全局组件

通过Vue的静态方法(component)定义,全可在所有组件中使用。语法如下:

<div id="app">
    <!-- 使用组件 -->
    <my-header></my-header>
</div>
<script type="text/javascript">
   //定义全局组件
   Vue.component("my-header",{
       template:"<div>我是全局组件</div>"
   })
   let app = new Vue({
        el:"#app"
  })
</script>

3. 局部组件

在父组件的 components 属性中定义。

3.1 定义组件对象

  • 组件对象名,采用驼峰法命名
  • 组件对象的配置项与Vue实例的配置项相似,data 数据项除外(组件对象中,data是一个方法)

3.2 定义组件模板

组件模板中,必有一个根元素,不能直接写h1、p、span、a等内容

3.3 注册组件

注册组件,组件在哪里使用,就注册到哪里

3.4 使用组件

定义组件时用的驼峰法,使用时将驼峰法转换为帕斯卡命名

4. template 语法规则

组件对象的template属性用来设置组件的模板内容,模板内容有3种写法:

  • 直接写在字符串中
<div id="app">
    <my-header></my-header>
</div>
<script type="text/javascript">
    let MyHeader = {
        template:'<div><h1>我是头部局部组件:{{name}}</h1></div>',
        data(){
            return {
                name:"局部组件"
            }
        }
    }
    let app = new Vue({
        el:"#app",
        components:{
            MyHeader
        }
  })
</script>
<div id="app">
    <my-header></my-header>
</div>
<script type="text/x-template" id="my-header">
    <div>
        <h3>我是头部局部组件</h3>
        <p>{{name}}</p>
    </div>    
</script>
<script type="text/javascript">
    let MyHeader = {
        template:'#my-header',
        data(){
            return {
                name:"局部组件"
            }
        }
    }
    let app = new Vue({
        el:"#app",
        components:{
            MyHeader
        }
  })
</script>

5. 组件间的相互通信

组件实例是孤立的,不可在子组件中直接用父组件中的数据(组件特性:高内聚、低耦合)

父组件通过 props 向下传递数据,子组件通过 emit 向上发射事件传递数据

5.1 父传子

  • 先在父组件中定义数据

  • 在父组件的模板中,通过属性绑定把数据绑定在子组件上,语法:子组件 :变量名=”数据项”

  • 在子组件中定义props属性,用来接收父组件传递的数据

  • 在子组件模板中使用数据

  • 在子组件的函数中使用数据

<div id="app">
    {{number}}
    <!-- 2. 把数据绑定在子组件上 -->
    <my-collapse :num="number"></my-collapse>
</div>
<template id="my-collapse">
    <div>
        <!-- 4. 在子组件中使用数据 -->
        <p>{{num}}</p>
        <p>{{Say()}}</p>
    </div>    
</template>
<script type="text/javascript">
  let MyCollapse = {
    template:'#my-collapse',
    props:{
            //3. 接受父组件传递的数据,Numder类型约束,表示传递过来的数值类型
      num:{
        type:Number,
        default:0,
        required:true
      }
    },
    methods:{
            //5. 在子组件的函数中使用数据
          Say(){
             console.log(this.num)
          }
      }
   }
   let app = new Vue({
       el:"#app",
       data:{
           //1. 定义父组件的数据项
           number:1000
       },
       components:{
           MyCollapse
       }
 })
</script>

  • props细节:每个数据项,都可有3个属性进行约束
    • type:类型约束,约束父组件给子组件传递的数据类型。类型包括:Object、Array、Number、String、Boolean
    • default:指定默认值,若父组件未传递数据,可指定默认值
    • required:指定该数据项是否必须传递

5.2 子传父

  • 在子组件中添加事件监听,通过$emit从子组件向父组件发射一个事件
  • 在父组件中接收子组件发射过来的事件,格式:<子组件 @子组件事件名=”父组件要执行的方法”>
  • 在父组件中定义方法接收子组件传递的事件及数据

注:子组件上的事件名@addmsg不能使用驼峰法

<div id="app">
    <p>{{content}}</p>
    <!-- 3. 在父组件中接收子组件发射过来的事件 -->
    <my-collapse @addmsg="receive"></my-collapse>
</div>
<template id="my-collapse">
    <div>
        <input v-model="msg" type="" name="">
        <!-- 2. 在子组件中添加事件监听 -->
        <button @click="sendMsg">按钮</button>
    </div>    
</template>
<script type="text/javascript">
    let MyCollapse = {
        template:'#my-collapse',
        data(){
            return {
                msg:''
            }
        },
        methods:{
            //1.从子组件向父组件发射事件,参数1:事件名;参数2:传递的数据
            sendMsg(){
                this.$emit("addmsg",this.msg)
            }
        }
    }
    let app = new Vue({
        el:"#app",
        data:{
            content:''
        },
        components:{
            MyCollapse
        },
        methods:{
            //4. 在父组件中定义方法接收子组件传递的事件及数据,参数是子组件传递的数据
            receive(d){
                return this.content=d
            }
        }
  })
</script>

6. 插槽 slot

插槽,即一个占位符,能在不同环境下,传递不同的参数,并得到不同的效果,在Vue中通过slot标签实现

思路:先在子组件中定义一个占位符(插槽),再使用真实的内容替换这个插槽

6.1 单个插槽

当子组件模板只有一个无属性的插槽时,父组件传入的整个内容片段将插入到插槽所在的DOM位置,并替换掉插槽本身

    <div id="app">
        <son>
            <h3>只是标题</h3>
            <p>这是段落</p>
        </son>
    </div>
    <template id="son">
        <div>
            <slot></slot>
        </div>
    </template>
    <script type="text/javascript">
        let Son = {
            template:'#son'
        }
        let app = new Vue({
            el:'#app',
            components:{
                Son
            }
        })        
    </script>

6.2 具名插槽

若有多个插槽(占位符),通过name属性加以区分,这种插槽就是具名插槽(可更灵活的管理组件的内容)

  • 先定义插槽(占位符),即将内容不确定的地方使用插槽占个位置
  • 再使用插槽,即使用真实内容替换占位符
  <div id="app">
        <son>
            <h3 slot="title">这是标题</h3>
            <p slot="content">这是段落</p>
        </son>
    </div>
    <template id="son">
        <div>
            <slot name="title"></slot>
            <slot name="content"></slot>
        </div>
    </template>

7. 深入理解 Vue 实例

通过 new Vue() 获得一个对象,即 Vue实例,Vue实例提供如下属性、方法:

7.1 Vue实例属性

  • $el,获取挂着 Vue 实例的元素
  • $data,获取 Vue 实例的数据项
<div id="app"></div>
<script type="text/javascript">
    let app = new Vue({
        el:'#app',
        data:{
            name:"David",
            age:20
        }     
    })
    console.log(app.$el);
    console.log(app.$data);
</script>

  • $refs,获取对DOM元素的引用

Vue 侧重于数据驱动,而jQuery侧重于dom,Vue提供了 $refs 属性对dom元素进行灵活的操作,具体使用:

    • 在元素上添加一个属性ref:<标签 ref=“keyword”
    • 在Vue实例中,通过this.$refs获取所有的dom引用
<div id="app">
        <a href="" ref="oa">超链接</a>
        <button @click="setStyle">点击切换</button>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            methods:{
                setStyle(){
                    //找到DOM节点
                    console.log(this.$refs)
                    console.log(this.$refs.oa)
                    this.$refs.oa.style.textDecoration='none'
                    this.$refs.oa.style.color='red'
                }
            }
        })        
    </script>

7.2 Vue实例方法

  • $mount,手动设置挂载点
  <div id="app">
        {{name}}
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
                name:"David"
            }
        })    
        app.$mount('#app')
    </script>
  • $watch,侦听器,监听数据项、计算属性值的变化,一旦值变化,则自动调用$watch方法

将所有的异步操作,都写在watch里面进行实现

  <div id="app">
        出生年月:
        <input v-model="birthday" type="" name=""><br>
        年龄:<p>{{age}}</p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                birthday:'',
                age:0
            },
            watch:{
                birthday(){
                    setTimeout(()=>{
                        this.age = new Date().getFullYear()-new Date(this.birthday).getFullYear();
                    },3000)
                }
            }
        })        
    </script>

8. Vue 实例的生命周期

实例化的Vue对象(根组件)以及自定义的组件对象都有生命周期,Vue 设计者为方便调试程序,提供了8个钩子函数:

    <div id="app">
      {{name}}    
    </div>
    <script type="text/javascript">
        let app = new Vue({
            data:{
                name:'David'
            },
            beforeCreate(){
                alert('beforeCreate')
            },
            created(){
                alert('created')
            },
            beforeMount(){
                alert('beforeMount')
            },
            mounted(){
                alert('mounted')
            },
            beforeUpdate(){
                alert('beforeUpdate')
            },
            updated(){
                alert('updated')
            },
            beforeDestory(){
                alert('beforeDestory')
            },
            destroyed(){
                alert('destroyed')
            }
        })    
        app.$mount('#app')
        app.$destroy('name')    
    </script>

生命周期函数作用:在不同的阶段,做相应的工作

  • created阶段,初始化数据,创建数据对象
  • mounted阶段,使用数据项替换模板,即将数据挂载到DOM元素节点上
  • updated阶段,当DOM节点中的数据发生改变,在此阶段进行更新

9. 动态组件

可定义多个组件,再使用 :is 属性动态地在多个组件之间切换

语法:<component v-bind:is=”组件名”></component>

Component 相当于一个占位符,具体显示哪个组件,通过:is指定

    <div id="app">
        <span @click="currentCom='FirstCom'">第一个</span>
        <span @click="currentCom='SecondCom'">第二个</span>
        <component :is="currentCom"></component>
    </div>
    <template id="com1">
        <div>第一个组件</div>
    </template>
    <template id="com2">
        <div>第二个组件</div>
    </template>
    <script type="text/javascript">
        let FirstCom={
            template:'#com1',
            mounted(){
                console.log("第一个被渲染")
            }
        }
        let SecondCom={
            template:'#com2',
             mounted(){
                console.log("第二个被渲染")
            }
        }
        let app = new Vue({
            el:"#app",
            data:{
                currentCom:''
            },
            components:{
                FirstCom,
                SecondCom
            }
        })
    </script>

  • keep-alive 组件

无 keep-alive 组件时,每次切换组件都重新创建一次组件,使用 keep-alive后,会将创建过的组件保存在内存中,以后使用时直接使用,而不会每次重新创建

    <div id="app">
        <span @click="currentCom='FirstCom'">第一个</span>
        <span @click="currentCom='SecondCom'">第二个</span>
        <keep-alive>
            <component :is="currentCom"></component>
        </keep-alive> 
    </div>
    <template id="com1">
        <div>第一个组件</div>
    </template>
    <template id="com2">
        <div>第二个组件</div>
    </template>
    <script type="text/javascript">
        let FirstCom={
            template:'#com1',
            mounted(){
                console.log("第一个被渲染")
            }
        }
        let SecondCom={
            template:'#com2',
             mounted(){
                console.log("第二个被渲染")
            }
        }
        let app = new Vue({
            el:"#app",
            data:{
                currentCom:''
            },
            components:{
                FirstCom,
                SecondCom
            }
        })
    </script>

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!

相关课程