vue学记笔记(五) 组件

组件

Vue 的核心就在于组件。组件的作用就是:复用。

小到一个按钮,大到一个页面都可以是组件

组件的三元素

每一个组件都必须包括三元素

  • template (用来存放 html)

  • script (用来写 js)

  • style (用来写 css)

  • 这里千万注意的是组件必须要大写,我这里是因为格式化所以变小写。实际要大写

特别注意的就是组件外面必须有一个包裹层,否则直接报错误

<template>
  <div class="login">
    <header></header>
    <div class="loginbox_wrap">
      <main></main>
    </div>
    <footer></footer>
  </div>
</template>

<script>
  import Header from '@/pages/common/Header'
  import Footer from '@/pages/common/Footer'
  import Main from '@/pages/Login/components/Main'
  export default {
    data() {
      return {
        message: '登陆'
      }
    },
    components: {
      Header,
      Footer,
      Main
    }
  }
</script>

<style lang="less" scoped>
  /*mobile*/
  @media (max-width: 767px) {
    .loginbox_wrap {
      width: 100%;
      min-height: calc(100vh - 200px - 73px);
      background: white;
    }
  }

  /*pad*/
  @media (min-width: 768px) and (max-width: 1024px) {
    .loginbox_wrap {
      width: 100%;
      min-height: calc(100vh - 108px - 150px - 50px);
      background: #f3f3f3;
      padding-top: 50px;
    }
  }

  /*desktop*/
  @media (min-width: 1025px) {
    .loginbox_wrap {
      width: 100%;
      min-height: calc(100vh - 108px - 150px - 50px);
      background: #f3f3f3;
      padding-top: 50px;
    }
  }
</style>

组件的引入必须有三点

  • 第一步:引入组件(import)

  • 第二步: 注册组件(components)

  • 第三步: 使用组件(自定义标签)

  • 这里千万注意的是组件必须要大写,我这里是因为格式化所以变小写。实际要大写

<header>
  <div class="login">
    <header></header>
    <main></main>
    <footer></footer>
  </div>
</header>

<script>
  import Header from '@/pages/common/Header'
  import Footer from '@/pages/common/Footer'
  import Main from '@/pages/Login/components/Main'
  export default {
    data() {
      return {
        message: '登陆'
      }
    },
    components: {
      Header,
      Footer,
      Main
    }
  }
</script>

<style lang="less" scoped></style>

组件之间的数据传递

组件之间的数据传递有两种

  • 父子组件

  • Vuex

  • 总线机制

  • 卡槽

父子组件

父子组件传值就两点

  • 传递数据 props

  • 子组件改变数据

父组件

  • 通过绑定:来传递数据,这样就把数据传递过去了,监听子组件传过来的事件,来调用父组件的方法改变值
<template>
  <div class="login">
    <header></header>
    <div class="loginbox_wrap">
      <main :info="message" :infoflag="flag" @changeflag="switchflag"></main>
    </div>
    <footer></footer>
  </div>
</template>

<script>
  import Header from '@/pages/common/Header'
  import Footer from '@/pages/common/Footer'
  import Main from '@/pages/Login/components/Main'
  export default {
    data() {
      return {
        message: '登陆',
        flag: false
      }
    },
    components: {
      Header,
      Footer,
      Main
    },
    methods: {
      switchflag(content) {
        this.flag = content
      }
    }
  }
</script>

<style lang="less" scoped></style>

子组件

  • 通过 props 接受数据

  • 发射出一个自定义事件来改变父元素的值,然后传递新的值,子组件永远不能直接改变父元素的值

<template>
  <div class="login">
    {{info}} ----{{infoflag}}
    <button @click="changedata"></button>
  </div>
</template>
<script>
  export default {
    props: ['info', 'infoflag'],
    data() {
      return {
        message: '子组件'
      }
    },

    methods: {
      changedata() {
        this.$emit('changeflag', true)
      }
    }
  }
</script>
<style></style>
  • 也可以有第二种父元素传递过来的值验证

  • 下面的例子说明 两个值必须要传递进来,一个是数字 一个是布尔

<template>
  <div class="login">
    {{info}} ----{{infoflag}}
    <button @click="changedata"></button>
  </div>
</template>
<script>
  export default {
    props: {
      info: {
        type: Number,
        required: true
      },
      infoflag: {
        type: Boolean,
        required: true
      }
    },
    data() {
      return {
        message: '子组件'
      }
    },

    methods: {
      changedata() {
        this.$emit('changeflag', true)
      }
    }
  }
</script>
<style></style>

Vue 总线机制

  • 总线机制主要是用在爷孙组件或者爷穷孙组件,这样省的一层层发射

第一步创建总线 挂载到 bus 属性上

Vue.prototype.bus = new Vue()

第二步 孙子组件发射出去自定义事件

this.bus.$emit('change', '想改变的值')

第三步 爷爷组件监听此事件

let _this = this
this.bus.$on('change', function(content) {
  _this.xxx = content
})

卡槽

  • 卡槽的作用就是有的时候我们不想只传递数据,还想传递 html 代码

匿名卡槽(只有一个卡槽,直接找默认)

  • 父组件 我想把 div 里面的 html 代码传递给子组件
<template>
  <div>
    <header></header>
    {{ message }}
    <Chacaoa>
      <div class="sloata">
        <p>A里面的数据</p>
      </div>
    </Chacaoa>
  </div>
</template>

<script>
  import Header from '@/components/common/Header'
  import Chacaoa from '@/components/common/Sloata'
  export default {
    data() {
      return {
        message: '首页'
      }
    },
    components: {
      Header,
      Chacaoa
    }
  }
</script>

<style lang="less" scoped>
  .sloata {
    width: 300px;
    height: 100px;
    background: blue;
    color: yellow;
  }
</style>
  • 子组件
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: '子组件',
        dataA: 'dataA里面的数据',
        dataB: 'dataB里面的数据'
      }
    }
  }
</script>

<style lang="less" scoped></style>

具名卡槽

  • 卡槽不止一个,需要传递多个 html 代码(署名)

  • 父组件

<template>
  <div>
    <header></header>
    {{ message }}
    <Chacaoa>
      <div class="sloata" slot="kaocaoa">
        <p>A里面的内容</p>
      </div>
      <div class="sloatb" slot="kaocaob">
        <p>B里面的内容</p>
      </div>
    </Chacaoa>
  </div>
</template>

<script>
  import Header from '@/components/common/Header'
  import Chacaoa from '@/components/common/Sloata'
  export default {
    data() {
      return {
        message: '首页'
      }
    },
    components: {
      Header,
      Chacaoa
    }
  }
</script>

<style lang="less" scoped>
  .sloata {
    width: 300px;
    height: 100px;
    background: blue;
    color: yellow;
  }
  .sloatb {
    width: 300px;
    height: 100px;
    background: red;
    color: black;
  }
</style>
  • 子组件
<template>
  <div>
    <slot name="kaocaoa"></slot>
    <slot name="kaocaob"></slot>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: '子组件',
        dataA: 'dataA里面的数据',
        dataB: 'dataB里面的数据'
      }
    }
  }
</script>

<style lang="less" scoped></style>

卡槽里面子组件想给父组件传值

  • 只有利用 slot-scope

  • 父组件

<template>
  <div>
    <header></header>
    {{ message }}
    <Chacaoa>
      <div class="sloata" slot="kaocaoa" slot-scope="shuju1">
        <p>{{ shuju1.data }}</p>
      </div>
      <div class="sloatb" slot="kaocaob" slot-scope="shuju2">
        <p>{{ shuju2.data }}</p>
      </div>
    </Chacaoa>
  </div>
</template>

<script>
  import Header from '@/components/common/Header'
  import Chacaoa from '@/components/common/Sloata'
  export default {
    data() {
      return {
        message: '首页'
      }
    },
    components: {
      Header,
      Chacaoa
    }
  }
</script>

<style lang="less" scoped>
  .sloata {
    width: 300px;
    height: 100px;
    background: blue;
    color: yellow;
  }
  .sloatb {
    width: 300px;
    height: 100px;
    background: red;
    color: black;
  }
</style>
  • 子组件
<template>
  <div>
    <slot name="kaocaoa" :data="dataA"></slot>
    <slot name="kaocaob" :data="dataB"></slot>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: '子组件',
        dataA: 'dataA里面的数据',
        dataB: 'dataB里面的数据'
      }
    }
  }
</script>

<style lang="less" scoped></style>

Vuex 下章在重点介绍


文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录