欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue.js 组件

程序员文章站 2022-05-18 09:05:07
1. 组件介绍 组件(component),vue.js最强大的功能之一 作用:封装可重用的代码,通常一个组件就是一个功能体,便于在多个地方都能调用该功能体 根组件:我们实例化的Vue对象就是一个组件,且是所有组件的根组件 分类:全局组件,局部组件 注:每个组件都是Vue的实例对象 2. 全局组件 ......

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 使用组件

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

<div id="app">
    <!-- 4.使用组件 -->
    <my-header></my-header>
</div>
<!-- 2.定义组件模板 -->
<template id="my-header">
    <div>
        <h3>我是头部局部组件</h3>
        <p>{{name}}</p>
    </div>
</template>
<script type="text/javascript">
    //1.定义局部组件
    let MyHeader = {
        template:'#my-header',//组件的模板,#my-header指id为my-header的模板
        data(){
            return {
                name:"局部组件"//数据项
            }
        }
    }
    let app = new Vue({
        el:"#app",
        //3.注册组件
        components:{
            MyHeader//将MyHeader 这个组件注册到app根组件中
        }
  })
</script>

Vue.js 组件

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>
  • 将模板内容写在template标签中(例子
  • 将模板内容写在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 向上发射事件传递数据Vue.js 组件

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>

Vue.js 组件

  • 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>

Vue.js 组件

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>

Vue.js 组件

  • $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>

Vue.js 组件

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>

Vue.js 组件

  • 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>

Vue.js 组件