24

我正在使用带有两个页面的Vue 路由器:

let routes = [
    {
        path: '/',
        component: require('./components/HomeView.vue')
    },
    {
        path: '/intro',
        component: require('./components/IntroView.vue')
    }
]

这很好用,除了我的每个组件都有不同的主体样式:

主视图.vue:

<template>
    <p>This is the home page!</p>
</template>

<script>
    export default {

    }
</script>

<style>
    body {
        background: red;
    }
</style>

介绍视图.vue:

<template>
    <div>
        <h1>Introduction</h1>
    </div>
</template>

<script>
    export default {

    }
</script>

<style>
    body {
        background: pink;
    }
</style>

我的目标是让这两个页面具有不同的背景样式(最终在它们之间进行过渡)。但是在我去home路线(有red背景)的那一刻,然后单击intro路线,背景颜色保持不变red(我希望它变为pink)。

编辑: index.html:

  <body>
    <div id="app">
        <router-link to="/" exact>Home</router-link>
        <router-link to="/intro">Introduction</router-link>
        <router-view></router-view>
    </div>
    <script src="/dist/build.js"></script>
  </body>
4

8 回答 8

57

我让它与生命周期挂钩 beforeCreate和全局样式表一起工作。在global.css

body.home {
    background: red;
}
body.intro {
    background: pink;
}

<script>部分HomeView.vue

export default {
    beforeCreate: function() {
        document.body.className = 'home';
    }
}

和中类似IntroView.vue

于 2017-06-14T12:17:37.450 回答
8
watch: {
  $route: {
    handler (to, from) {
      const body = document.getElementsByTagName('body')[0];
      if (from !== undefined) {
        body.classList.remove('page--' + from.name.toLowerCase());
      }
      body.classList.add('page--' + to.name.toLowerCase());
    },
    immediate: true,
  }
},

另一个相当简单的解决方案,将它添加到您的基础 App.vue 文件中。to.name 可以替换为 to.meta.class 或类似的更具体的东西。这是一个很好的一次性解决方案,但它永远有效。

于 2018-11-28T23:04:01.430 回答
3

或者你可以使用这个

它允许使用 vue-router 控制您的页面正文类。遇到类似问题时写了这个。它还指单击组件时将类添加到正文?

于 2017-11-03T14:14:56.297 回答
3

如果课程是特定于视图的,这可能会有所帮助

methods: {
  toggleBodyClass(addRemoveClass, className) {
    const el = document.body;

    if (addRemoveClass === 'addClass') {
      el.classList.add(className);
    } else {
      el.classList.remove(className);
    }
  },
},
mounted() {
  this.toggleBodyClass('addClass', 'mb-0');
},
destroyed() {
  this.toggleBodyClass('removeClass', 'mb-0');
},

methods部分移动到 mixin,然后代码可以是 DRY。

于 2018-08-06T11:00:42.670 回答
3

当我想修改htmlbody标签的样式以及#app特定路线上的容器时遇到了一个问题,我发现由于各种原因,这可能非常复杂。

通读后:

在你的App.vue 中(可以认为是集中状态):

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'my-app',
    methods: {
      handleStyles () {
        // Red style to the body tag for the home page
        if (['/'].includes(this.$route.path)) document.body.className = 'bg-red'
        // Pink style to the body tag for all other pages
        else if (document.body.classList.contains('bg-red')) document.body.className = 'bg-pink'
      }
    },
    // Handle styles when the app is initially loaded
    mounted () {
      this.handleStyles()
    },
    // Handle styles when the route changes
    watch: {
      '$route' () {
        this.handleStyles()
      }
    }
  }
</script>

<style>
  .bg-red {
    background: red;
  }
  .bg-pink {
    background: pink;
  }
</style>

因此,对于路线/,您将获得红色样式,而对于所有其他路线,则应用粉红色样式。

handleStyles逻辑可以通过钩子处理,但是beforeCreated在我的情况下,这只会影响htmlbody样式,但是#app渲染路由器视图的元素只有在安装 dom 时才可用,所以我认为它稍微多一点可扩展的解决方案。

于 2018-11-20T20:42:35.643 回答
0

您也可以使用afterEach钩子直接在路由器文件中执行此操作:

mainRouter.afterEach((to) => {
    if (["dialogs", "snippets"].includes(to.name)) {
        document.body.style.backgroundColor = "#F7F7F7";
        // or document.body.classList.add(className);
    } else {
        document.body.style.backgroundColor = "#FFFFFF";
        // or document.body.classList.remove(className);
    }
});

afterEach钩子文档

to是一个路由对象,其中包含路由名称(如果已命名)、路径等 。所有道具的文档

于 2019-04-30T13:39:07.500 回答
0

最佳答案是正确的,但需要一些优化。因为当刷新该页面
时,该答案不起作用。原因是设置你想要的样式时没有加载dom。所以,更好的解决方案是:

beforeCreate() {
  this.$nextTick(() => {
    document.querySelector('body').style.backgroundColor = '#f2f2f2'
  })
},
beforeDestroy() {
  document.querySelector('body').style.backgroundColor = ''
},

通过将样式设置处理程序包装在 中this.$nextTick,将在加载 dom 时设置样式。所以刷新页面时可以得到正确的样式

于 2021-11-29T03:31:28.830 回答
-2

您可以在样式元素中使用作用域属性。然后样式将仅限于该 vue 文件。

主视图.vue:

<template>
    <p>This is the home page!</p>
</template>

<script>
    export default {

    }
</script>

<style scoped>
    body {
        background: red;
    }
</style>

介绍视图.vue:

<template>
    <div>
        <h1>Introduction</h1>
    </div>
</template>

<script>
    export default {

    }
</script>

<style scoped>
    body {
        background: pink;
    }
</style>
于 2019-05-17T18:09:50.107 回答