html & html5, Javascript, 原创,

vue element 根据文章内容动态修改网页标题Title、描述Description,关键字Keywords等

话不多说,直接上解决方法,先说下 关键的目录结构

website:
|-public
| |–index.html
|-src
| |-components
| | |-CommonFooter.vue
| |-router
| | |-index.ts
| | -views
| | |-Blog
| | | |-Detail.vue
| |-App.vue
| |-main.ts

1.在index.html中配置好相关元素,如下所示:author,description,keywords 和title

    <title>风火家人</title>
    <meta name="author" content="chenxue4076@163.com" />
    <meta name="description" content="技术总结,个人开发日记" />
    <meta name="keywords" content="技术总结,服务器,开发,PHP,Python,AiStudio,CMS,MySql" />

2.我并没有直接在App.vue中直接添加自定义标签,而是引用了compoents下的CommonFooter.vue, 按道理在App.vue中直接使用应该是没有问题的, 只能让读者自己去尝试看下,下面是我在App.vue应用CommonFooter.vue的代码:

<template>
  <el-container id="app" direction="vertical">
/*省略掉了很多内容*/
    <CommonFooter />
  </el-container>
</template>
<script>
import CommonFooter from "@/components/CommonFooter.vue";
export default {
/*省略掉了很多内容*/
  components: {
    CommonFooter
  }
};
</script>

3.CommonFooter.vue 配置自定义标签如下。其目的是为首页或列表页展示标题、描述、关键字等使用。后面使用 dataset中的 title,description等获取内容。

<template>
  <el-footer class="page-footer" height="auto">
/*省略掉了很多内容*/
    <div v-web-title :data-title="WebTitle" />
    <div v-web-description :data-description="WebDescription" />
    <div v-web-keywords :data-keywords="WebKeywords" />
    <div v-web-author :data-author="WebAuthor" />
  </el-footer>
</template>
<script lang="ts">
import {
  Component,
  Vue
} from "vue-property-decorator";
@Component
export default class CommonFooter extends Vue {
  WebTitle: string = "";
  WebDescription: string = "";
  WebKeywords: string = "";
  WebAuthor: string = "";
}
</script>

4.给路由文件添加 title,description,keywords,author等meta信息,作为通用的描述信息meta。

const routes = [
  {
    path: "/",
    component: () => import("../views/BookNote/Index.vue"),
    meta: {
      title: "书摘" ,
      description: "记录看过的那些书",
      keywords: "文摘,经典语句,名人名言,读书笔记",
      author: "chenxue4076@163.com"
    },
    children: [
      {
        path: "",
        name: "booknote",
        component: () => import("../views/BookNote/List.vue")
      }
    ]
  },
  {
    path: "/blog",
    component: () => import("../views/Blog/Index.vue"),
    meta: {
      title: "程序开发经验",
      description: "开发经验总结,做过的开发重点记录",
      keywords:
        "CentOS,CodeIgniter,Docker,Git,Go,Golang,MySql,PHPOffice,SSL,Wechat,算法,加密解密,Nginx,PHP,服务器",
      author: "chenxue4076@163.com"
    },
    children: [
      {
        path: "",
        name: "blog",
        component: () => import("../views/Blog/List.vue")
      },
      {
        path: "index",
        name: "blog_index",
        component: () => import("../views/Blog/List.vue")
      },
      {
        path: ":year/:month/:slug",
        name: "blog_detail",
        component: () => import("../views/Blog/Detail.vue")
      }
    ]
  },

5.因为是 CommonFooter.vue是针对列表或一些不需要根据详细内容配置标题和描述的,比如非博客的标题和描述等。所以到了博客的详细页中我们还需要再定义一次这些标签。如Blog/Detail.vue中的。
使用 this.$set给 定义的WebTitle等赋值。

<template>
  <div class="blog-detail">
    <div v-web-title :data-title="WebTitle" />
    <div v-web-description :data-description="WebDescription" />
    <div v-web-keywords :data-keywords="WebKeywords" />
    <div v-web-author :data-author="WebAuthor" />
    <article>
      <header>
        <h2 v-html="itemInfo.PostTitle"></h2>
      </header>
      <section
        class="blog-content-info"
        v-html="itemInfo.PostContent"
      ></section>
    </article>
  </div>
</template>
<script lang="ts">
import axios from "axios";
import GlobalFunctions from "@/api/functions";
export default {
  itemInfo: Object,
  WebTitle: String,
  WebDescription: String,
  WebKeywords: String,
  WebAuthor: String,
  data() {
    return {
      itemInfo: {},
      WebTitle: "",
      WebDescription: "",
      WebKeywords: "",
      WebAuthor: ""
    };
  },
  mounted() {
    //获取详细博客
    this.handleBlogDetail();
  },
  watch: {
    $route(to, from) {
      this.handleBlogDetail();
    }
  },
  methods: {
    handleBlogDetail() {
      axios
        .get("/api/windigniter/blog/detail/" + this.$route.params.slug, {
          params: {}
        })
        .then(response => {
          if (response.data.Status) {
            this.itemInfo = response.data.Message;
            //设置标题、描述、关键字等
            this.$set(
              this,
              "WebTitle",
              response.data.Message.PostTitle + "-风火家人"
            );
            this.$set(this, "WebDescription", response.data.Message.PostTitle);
            this.$set(this, "WebKeywords", response.data.Message.PostTitle);
            this.$set(this, "WebAuthor", response.data.Message.UserEmail);
            return;
          }
          return;
        });
    }
  }
};
</script>

5.在 main.ts 文件中添加自定义标签,和路由处理。这里有需要注意的地方。

1.修改标题:我看有人直接使用 document.title = to.meta.title。但是我配置的上面路由方式这种并不起作用,需要使用 document.title = to.matched[0].meta.title

2.修改描述、关键字等信息。开始我使用的是 document.getElementsByTagName(“meta”)[“description”] 这种貌似在命令行里看到生效了,js出来的也对,但是看 html代码中并没有被修改,后面通过不断尝试,终于测出了正确的使用方式: document.getElementsByName(“description”)[0].content = to.matched[0].meta.description

//根据路由信息更新网页标题
router.beforeEach((to, from, next) => {
  //路由发生变化修改页面title
  if (to.matched[0].meta.title) {
    document.title = to.matched[0].meta.title;
  }
  if (to.matched[0].meta.description) {
    document.getElementsByName("description")[0].content =
      to.matched[0].meta.description;
  }
  if (to.matched[0].meta.keywords) {
    document.getElementsByName("keywords")[0].content =
      to.matched[0].meta.keywords;
  }
  if (to.matched[0].meta.author) {
    document.getElementsByName("author")[0].content = to.matched[0].meta.author;
  }
  next();
});

//自定义修改网页标题,简介,关键字
Vue.directive("web-title", {
  update: function(el, binding, vnode, oldVnode) {
    const { value } = binding;
    if (el.dataset.title) {
      document.title = el.dataset.title;
    } else if (value && value.title) {
      document.title = value.title;
    }
  }
});
Vue.directive("web-description", {
  update: function(el, binding, vnode, oldVnode) {
    const { value } = binding;
    if (el.dataset.description) {
      document.getElementsByName("description")[0].content =
        el.dataset.description;
    } else if (value && value.description) {
      document.getElementsByName("description")[0].content = value.description;
    }
  }
});
Vue.directive("web-keywords", {
  update: function(el, binding, vnode, oldVnode) {
    const { value } = binding;
    if (el.dataset.keywords) {
      document.getElementsByName("keywords")[0].content = el.dataset.keywords;
    } else if (value && value.keywords) {
      document.getElementsByName("keywords")[0].content = el.dataset.keywords;
    }
  }
});
Vue.directive("web-author", {
  update: function(el, binding, vnode, oldVnode) {
    const { value } = binding;
    if (el.dataset.author) {
      document.getElementsByName("author")[0].content = el.dataset.author;
    } else if (value && value.author) {
      document.getElementsByName("author")[0].content = value.author;
    }
  }
});

现在终于可以正常显示博客详情的标题和描述等信息了。具体效果见 本站主站博客模块

(1909)

Related Post