人类高质量vue学习笔记(三)

784 阅读3分钟

1. 组件

组件:component

举个例子:我们登录管理系统的后台,发现有左侧的菜单栏、头部的管理员信息、中间的数据信息、底部的友情链接等,我们可以把这些不同的页面布局看成一个个的组件,然后像拼积木一样把他们拼起来,这些组件就构成了一个完整的页面,如下图所示:

组件的作用:

  • 减少 vue 实例中的代码量
  • 组件可以重复使用:"代码共享"
  • 便于开发人员进行维护

2. 全局注册

全局注册完,任何 vue 实例都可以使用该组件。

2.1 全局注册语法:

Vue.component('login',{
  template:'<div><span>这是登录组件</span></div>'
});
  • 参数一:组件的名称
  • 参数二:组件的配置,template 中用来写 html 代码

2.2 使用组件:

<login></login>  
  • 如果组件名是以驼峰形式命名,则在使用的时候组件名必须是“小写单词-小写单词”,例如:
<div id="app">
  <!-- 2.组件使用 -->  
  <new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    //  1.注册全局组件 
	Vue.component('newComponent', {
      template: '<div> 这瓜保熟吗? </div>'
    })
 const app = new Vue({
    el: '#app'
  })
</script>

运行结果:

3. 局部注册

注册的组件只能在当前 vue 实例中使用。

    1. 先定义组件
    1. 必须在 vue 实例中注册组件
    1. 使用组件

3.1 第一种注册方式

<div id="app">
    <!-- 3. 使用组件,注:组件可以重复使用 -->
    <new-component></new-component>
    <new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 1. 定义局部组件
    var newComponent = {
        template: '<div>我是个局部组件,只能在当前vue实例中使用!</div>'
    }
    const app = new Vue({
        el: "#app",
        // 2. 在 vue 实例中注册组件,切记只有在这里注册过后才能使用
        components: {
            'newComponent': newComponent
        }
    })
</script>

运行结果:

3.2 第二种注册方式

将 template 中的 html 代码单独剥离出来放到 template 标签里面。

<div id="app">
    <!-- 4. 使用组件,注:组件可以重复使用 -->
    <new-component></new-component>
    <new-component></new-component>
</div>

 // 1. 声明局部组件模板
<template id="newTemplate">
   <div>我是个局部组件,只能在当前vue实例中使用!</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 2. 定义变量保存模板对象
    var newComponent = {
        template: '#newTemplate'
    }
    // 3. 注册组件
    const app = new Vue({
        el: "#app",
        components: {
            'newComponent': newComponent
        }
    })
</script>

注:无论是全局组件还是局部组件,都可以重复使用。template中必须有且仅有一个 root 元素,这里一般指的是 div 标签

4. 组件内部 data 中的数据

我们知道在 vue 实例中可以使用 data 中的数据,在组件内部中同样可以使用 data 中的数据。

  • 组件中的 data 值必须是一个函数,这个函数必须要返回一个对象
  • 以 {{}} 形式使用 data 中的数据
<div id="app">
  <!-- 2.组件使用 -->  
  <new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    //  1.注册全局组件 
    Vue.component('newComponent', {
    // 组件中的 data 值必须是一个函数
     data: function(){
        //这个函数必须要返回一个对象
        return {
          price: 15,
          msg: "保熟"
        }
      },
      // {{}} 使用组件data中的数据
      template: '<div><p> 刘华强:这瓜多少钱一斤?</p> <p> 卖瓜的:{{price}} 元一斤</p><p> 刘华强:卧槽这瓜保熟吗?</p><p> 卖瓜的:{{msg}} </p></div>'
    })
 const app = new Vue({
    el: '#app'
  })
</script>

运行结果:

5. 组件传值

5.1 父组件向子组件传值

  • 父组件发送的属性值需要绑定到子组件的属性上面,下面例子中 :name 表示绑定子组件的属性是 name,:name="childName" 表示将父组件 childName 的值给了子组件的 name属性。
  • 子组件用属性 props 接收,下例中 props:["name"] 表示子组件用 name 来接收父组件的传值。
  • props 中的属性如果是驼峰形式,绑定的子组件的属性需要使用短横线的形式。例如 props:["childAge"] 则 :child-age="age"
<!-- 4. 父组件绑定子组件属性进行传值 -->
<div id="app">
   <p>父亲:{{username}}</p> 
   <child :name="childName" :child-age="age"></child>
</div>

<!-- 1. 定义组件模板 -->
<template id="child">
    <div>
        <p> 儿子姓名:{{ name }}</p>
        <p> 儿子年龄:{{ childAge }}</p>
    </div>
</template>

<script>
    // 2. 定义组件变量保存组件模板对象
    const child = {
        template: "#child",
        // 里面的属性用来接父组件的值
        props:["name","childAge"]
    }
    const app = new Vue({
        el: "#app",
        data: {
            username: "张翠山",
            childName:"张无忌",
            age:23
        },
        // 3. 注册组件
        components: {
            child
        },
        methods: {

        },
    })
</script>

5.2 子组件向父组件传值

  • 子组件用$emit()触发事件
  • $emit()第一个参数是事件名称,第二个参数是需要传递的数据
  • 父组件用 v-on 监听子组件的事件
<div id="app">
    <!-- 5. 通过事件绑定将参数传递给父组件的方法 -->
    <child @tell="fromChild"> </child>
</div>

<!-- 1. 定义儿子组件模板 -->
<template id="child">
    <div>
        <h2>我是儿子组件,点击我向父亲传值</h2>
        <button @click="change"> 点我</button>
    </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 2. 定于组件变量保存组件模板对象
    const child = {
        template: "#child",
        data() {
            return {
                name: "张无忌"
            }
        },
        methods: {
            change() {
                // 4. 触发事件
                this.$emit('tell', this.name);
            }
        },
    }
    const app = new Vue({
        el: "#app",
        data: {
            username: "张翠山"
        },
        // 3. 注册组件
        components: {
            child
        },
        methods: {
            fromChild(name) {
                console.log("儿子:"+name);
            }
        },
    })
</script>

运行结果: 上面例子讲解:

    1. 使用子组件时,通过 @tell 绑定了父组件的 fromChild 方法
    1. 点击子组件的按钮,通过$emit()触发 tell 事件,父组件通过 v-on 监听子组件的 tell 事件,其中 @tell 就是 v-on:tell 的缩写,父组件将监听到的数据传递给自己的 fromChild 方法。
    1. 父组件的 fromChild 方法打印出数据

6. 组件访问

6.1 父组件访问子组件数据

  • 使用子组件时用 $refs 给子组件定义一个别名
  • 使用 this.$refs.子组件别名可以获取子组件信息
<div id="app">
    <!-- 4. 使用组件,通过 ref 给子组件起一个别名 -->
    <new-component ref="firstChild"></new-component>
    <hr>
    <button @click="getFilmName">点我</button>
</div>

<!-- 1. 声明局部组件模板 -->
<template id="newTemplate">
    <div>我是个局部组件,只能在当前vue实例中使用!</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 2. 定义变量保存模板对象
    var newComponent = {
        template: '#newTemplate',
        data: function () {
            //这个函数必须要返回一个对象
            return {
                film: "扫黑风暴"
            }
        },
    }
    // 3. 注册组件
    const app = new Vue({
        el: "#app",
        data: {
            msg: ""
        },
        components: {
            'newComponent': newComponent
        },
        methods: {
            getFilmName(){
              // 5.this.$refs.firstChild.film 获取子组件的属性
                console.log("最近热播剧:"+this.$refs.firstChild.film);
            }
        },
    })
</script>

运行结果:

6.2 子组件访问父组件数据

  • 使用 this.$parent 访问父组件
<div id="app">
    <!-- 4. 使用组件 -->
    <new-component></new-component>
</div>

<!-- 1. 声明局部组件模板 -->
<template id="newTemplate">
    <div>
        <h2>这是子组件!</h2>
        <hr>
        <button @click="getFilmName">点我</button>
    </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 2. 定义变量保存模板对象
    var newComponent = {
        template: '#newTemplate',
        methods: {
            getFilmName(){
                console.log("最近热播剧:"+this.$parent.film);
            }
        },
    }
    // 3. 注册组件
    const app = new Vue({
        el: "#app",
        data: {
            film: "扫黑风暴"
        },
        components: {
            'newComponent': newComponent
        },
        methods: {

        },
    })
</script>

运行结果:

7. 组件插槽

    1. 新建组件,使用<slot>默认内容</slot> 展示默认内容
    1. 使用组件时,组件标签中间的内容覆盖 slot 标签里面的内容
    1. 使用组件插槽可以增加代码复用性

7.1 匿名插槽

设置默认值,组件标签有值就覆盖默认值,没有就显示默认值。

<div id="app">
  <!-- 2. 所有组件标签中嵌套的内容会替换掉slot,如果不传值则使用 slot 中的默认值  -->  
  <final></final>
  <final>贺芸是大boss!/final>
  <final>高明远是大boss!</final>
  <final>王政是大boss!</final>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
  // 1、定义全局组件,slot 插槽中设置默认值
  Vue.component('final', {
    template: `
      <div>
        <span>扫黑风暴大结局:</span>
        <slot>谁是大boss?</slot>
      </div>
    `
  });
  const  app = new Vue({
    el: '#app',
    data: {
    }
  });
</script>

运行结果:

7.2 具名插槽

就是给插槽设置个名字,使用组件的时候可以给特定名字的插槽设置值。

<div id="app">
  <!-- 2. 所有组件标签中嵌套的内容会替换掉slot,如果不传值则使用 slot 中的默认值  -->  
  <final></final>
  <final>贺芸是大boss!</final>
  <final>高明远是大boss!</final>
  <final><span slot="boss" style="color:red">打死都不剧透!!</span> </final>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
  // 1、定义全局组件,slot 插槽中设置默认值
  Vue.component('final', {
    template: `
      <div>
        <span>扫黑风暴大结局:</span>
        <slot name="boss">谁是大boss?</slot>
      </div>
    `
  });
  const  app = new Vue({
    el: '#app',
    data: {
    }
  });
</script>

运行结果: