当前位置:   article > 正文

vue实现多布局模式_vue、layout 布局

vue、layout 布局

1、目标效果

        源码地址:multipal-layout-demo: vue2实现多布局+暗黑模式

默认布局:头部宽度100%,侧边栏、内容区

顶部布局:头部宽度100%,内容区

侧边栏布局:侧边栏高度100%,头部、内容区

2、原理分析

(1)vuex文件

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. export default new Vuex.Store({
  5. state: {
  6. // 暗黑模式
  7. isDark: false,
  8. // 布局类型
  9. layoutType: 'default'
  10. },
  11. mutations: {
  12. // 修改暗黑模式
  13. set_is_dark(state, val) {
  14. state.isDark = val
  15. },
  16. // 修改布局类型
  17. set_layout_type(state, val) {
  18. state.layoutType = val
  19. }
  20. },
  21. actions: {
  22. },
  23. modules: {
  24. }
  25. })

        

(2)布局缩略图如何实现?用div + css 手动实现布局样式

        父组件传递一个布局类型数组,遍历此组件;用一个变量保存索引值,点击不同的布局类型项时切换索引并在vuex修改当前选中的布局类型

        将缩略图封装成组件:Thumbnail.vue

  1. <template>
  2. <!-- 缩略图 -->
  3. <div class="thumbnail">
  4. <div class="layout" v-for="(item, index) in layouts" @click="changeCheck(item, index)">
  5. <template v-if="item.type == 'default'">
  6. <div class="top" :style="{ background: isDark ? 'black' : '#fff' }"></div>
  7. <div class="left" :style="{ background: isDark ? 'black' : '#fff' }"></div>
  8. </template>
  9. <template v-if="item.type == 'top'">
  10. <div class="top" :style="{ background: isDark ? 'black' : '#fff' }"></div>
  11. </template>
  12. <template v-if="item.type == 'slide'">
  13. <div class="top"></div>
  14. <div class="left" :style="{ background: isDark ? 'black' : '#fff' }"></div>
  15. </template>
  16. <i class="el-icon-check" v-show="checked == index"></i>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. import { mapState } from 'vuex'
  22. export default {
  23. props: {
  24. // 布局类型数组
  25. layouts: {
  26. type: Array,
  27. default: () => []
  28. }
  29. },
  30. data() {
  31. return {
  32. // 当前选中值
  33. checked: 0,
  34. }
  35. },
  36. computed: {
  37. // 获取是否是暗黑模式,从而缩略图实现暗黑效果
  38. ...mapState(['isDark'])
  39. },
  40. methods: {
  41. // 切换选中值
  42. changeCheck(item, index) {
  43. this.checked = index
  44. this.$store.commit('set_layout_type', item.type)
  45. }
  46. }
  47. }
  48. </script>
  49. <style lang="less" scoped>
  50. .thumbnail {
  51. display: flex;
  52. width: 100%;
  53. .layout {
  54. position: relative;
  55. width: 50px;
  56. height: 50px;
  57. border: 1px solid gray;
  58. overflow: hidden;
  59. background: #f0f0f0;
  60. border-radius: 5px;
  61. cursor: pointer;
  62. .top {
  63. position: absolute;
  64. left: 0;
  65. top: 0;
  66. width: 100%;
  67. height: 25%;
  68. }
  69. .left {
  70. position: absolute;
  71. left: 0;
  72. top: 0;
  73. bottom: 0;
  74. width: 25%;
  75. height: 100%;
  76. }
  77. .el-icon-check {
  78. position: absolute;
  79. left: 50%;
  80. top: 50%;
  81. transform: translate(-50%, -50%);
  82. font-size: 20px;
  83. }
  84. }
  85. }
  86. </style>

(3)建立多个不同类型的布局文件: 

 

 侧边栏布局 :src/views/layout/SlideLayout.vue

  1. <template>
  2. <!-- 侧边栏布局 -->
  3. <div>
  4. <Sliderbar></Sliderbar>
  5. <Header></Header>
  6. <div class="content-box">
  7. <router-view />
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. import Sliderbar from '@/components/Sliderbar.vue'
  13. import Header from '@/components/Header.vue'
  14. export default {
  15. components: {
  16. Header,
  17. Sliderbar,
  18. },
  19. }
  20. </script>
  21. <style lang="less" scoped></style>

默认布局布局:src/views/layout/DefaultLayout.vue 

  1. <template>
  2. <!-- 默认布局 -->
  3. <div>
  4. <Header></Header>
  5. <Sliderbar></Sliderbar>
  6. <div class="content-box">
  7. <router-view />
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. import Header from '@/components/Header.vue'
  13. import Sliderbar from '@/components/Sliderbar.vue'
  14. export default {
  15. components: { Header, Sliderbar },
  16. }
  17. </script>
  18. <style lang="less" scoped></style>

顶部布局:src/views/layout/TopLayout.vue 

  1. <template>
  2. <!-- 顶栏布局 -->
  3. <div>
  4. <Header></Header>
  5. <div class="content-box">
  6. <router-view />
  7. </div>
  8. </div>
  9. </template>
  10. <script>
  11. import Header from '@/components/Header.vue'
  12. export default {
  13. components: {
  14. Header,
  15. },
  16. }
  17. </script>
  18. <style lang="less" scoped></style>

  

 (4)首页组件 Home.vue,Home.vue下面渲染二级路由 

 

  1. <template>
  2. <!-- vuex获取选中的布局类型 -->
  3. <div>
  4. <defaultLayout v-show="layoutType == 'default'"></defaultLayout>
  5. <slideLayout v-show="layoutType == 'slide'"></slideLayout>
  6. <topLayout v-show="layoutType == 'top'"></topLayout>
  7. </div>
  8. </template>
  9. <script>
  10. import defaultLayout from './layout/DefaultLayout.vue'
  11. import slideLayout from './layout/SlideLayout.vue'
  12. import topLayout from './layout/TopLayout.vue'
  13. import { mapState } from 'vuex'
  14. export default {
  15. components: { defaultLayout, slideLayout, topLayout },
  16. computed: {
  17. ...mapState(['layoutType'])
  18. },
  19. }
  20. </script>
  21. <style lang="less" scoped></style>

 (5)暗黑模式、布局类型变量都是保存在vuex中,因为多个组件之间进行数据通信比较方便!通过mapState取出vuex数据,然后通过computed接受mapState值,但如果想要直接修改mapState中的值则会报以下的错误:

         computed property "isDark" was assigned to but it has no setter.

        这是因为computed为只读的。不能直接修改computed的数据,要想修改则使用set

  1. computed: {
  2. ...mapState(['isDark']),
  3. // computed property "isDark" was assigned to but it has no setter. 这是因为computed为只读的。不能直接修改computed的数据,要想修改则使用set
  4. darkMode: {
  5. get() {
  6. return this.isDark
  7. },
  8. set(val) {
  9. this.$store.commit('set_is_dark', val)
  10. // 获取html根元素标签
  11. let html = document.documentElement
  12. if (val) {
  13. // html添加class="dark"选择器
  14. html.classList.add('dark')
  15. } else {
  16. // html移除class="dark"选择器
  17. html.classList.remove('dark')
  18. }
  19. }
  20. }
  21. },

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/82106
推荐阅读
相关标签
  

闽ICP备14008679号