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