Node.js从零开发博客(四)前台主题

Node.js从零开发博客(四)前台主题

2020年04月10日 阅读:6 字数:894 阅读时长:2 分钟

主要记录博客前台的nuxtServerInit状态数据管理,前台数据查询以及白天、黑夜主题切换等功能

1、状态数据

在nuxtServerInit请求所有页面都需要用到的数据,比如菜单、系统配置

const state = () => ({
  categories: [],
  configs: {}
})

const mutations = {
  SET_CATEGORY: (state, categories) => {
    state.categories = categories
  },
  SET_CONFIGS: (state, configs) => {
    state.configs = configs
  }
}

const actions = {
  async nuxtServerInit({ commit }, { req, $axios }) {
    // 获取菜单以及系统配置
    const { categories, configs } = await $axios.$get(`/general`)
    commit('SET_CATEGORY', categories)
    commit('SET_CONFIGS', configs)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

2、watchQuery

列表页监听分页、排序、标签参数改变,重新请求列表数据

mixins.js

export const listPage = {
  data () {
    return {
      total: 0,
      listPage: {
        page: 1,
        pageSize: 20
      },
      filters: {},
      dynamicTags: []
    }
  },
  methods: {
    /**
     * 列表分页切换
     * @param {Object} { page: 当前页, limit: 每页个数 }
     */
    changeListPage ({ page }) {
      const { name, params, query } = this.$route
      const [id] = params.id ? params.id.split('-') : ['list']
      this.$router.push({ name, params: { id: `${id}-${page}` }, query })
    },
    handleSearch () {
      const { name, params } = this.$route
      const [id] = params.id ? params.id.split('-') : ['list']
      const serachParams = this.filterParams(this.filters)
      this.$router.push({ name, params: { id: `${id}-1` }, query: serachParams })
    },
    /**
     * 删除筛选标签
     * @param {String} tag 列表标签
     */
    handleDeleteTag (tag) {
      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1)
      this.filters.tags = this.dynamicTags.join()
      this.handleSearch()
    },
    /**
     * 添加筛选标签
     * @param {String} tag 列表标签
     */
    handleAddTag (tag) {
      if (this.dynamicTags.includes(tag)) { return }
      this.dynamicTags.push(tag)
      this.filters.tags = this.dynamicTags.join()
      this.handleSearch()
    },
    /**
     * 剔除对象中值为空的属性
     * @param {Object} data 源对象
     * @returns {Object}
     */
    filterParams (data) {
      const target = {}
      for (const key in data) {
        if (data[key] !== '') {
          target[key] = data[key]
        }
      }
      return target
    }
  }
}

文章列表页

export default {
  name: 'ArticleList',
  mixins: [listPage],
  asyncData ({ params, query, $axios }) {
    // 请求数据
  },
  watchQuery: ['sortBy', 'orderBy', 'tags']
})

3、Dark Light模式

使用 @nuxtjs/color-mode 模块,实现白天、黑夜主题切换功能

styles/variables.scss

//theme
:root {
  --color-primary: #1890ff;
  --color-heading: #1f1f1f;
  --color-text: #434343;
  --color-secondary: #8c8c8c;
  --bg: #f5f5f5;
  --bg-normal: #fff;
  --border-color: #EBEEF5;
  --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.dark-mode {
  --color-primary: #1890ff;
  --color-heading: #f5f5f5;
  --color-text: #d9d9d9;
  --color-secondary: #8c8c8c;
  --bg: #000;
  --bg-normal: #1f1f1f;
  --border-color: rgba(255, 255, 255, .2);
}

nuxt.config.js

module.exports = {
  buildModules: [
    '@nuxtjs/color-mode'
  ],
  css: [
    '@/styles/variables.scss'
  ]
}

样式规则,使用var(变量)就可以获取当前主题下的变量值

body{
  background-color: var(--bg);
  color: var(--color-text);
  transition: background-color .3s;
}

4、代码高亮

使用prismjs来实现文章中的代码高亮功能

另一篇文章也有详细讲到:https://www.timelessq.com/article/detail/8

import Prism from 'prismjs'
import ClipboardJS from 'clipboard'

export default {
  name: 'ArticleDetail',
  mounted () {
    this.initPrism()
  },
  methods: {
    initPrism() {
      Prism.plugins.toolbar.registerButton('copy-to-clipboard', (env) => {
        const buttonElement = document.createElement('button')
        const iconElement = document.createElement('i')
        const tooltipElement = document.createElement('em')
        buttonElement.className = 'toolbar-item-button'
        iconElement.className = 'icon-fuzhi'
        tooltipElement.className = 'toolbar-item-button__tips'
        tooltipElement.innerText = '复制'
        buttonElement.appendChild(iconElement)
        buttonElement.appendChild(tooltipElement)

        const clipboard = new ClipboardJS(buttonElement, {
          text: () => {
            return env.code
          }
        })
        clipboard.on('success', () => {
          iconElement.className = 'icon-wancheng'
          clearTimeout(this.timer)
          this.timer = setTimeout(() => {
            iconElement.className = 'icon-fuzhi'
          }, 3000)

          // 复制成功,转载最好带上出处哟
        })
        clipboard.on('error', () => {
          // 复制失败了呢
        })
        return buttonElement
      })

      Prism.highlightAll()
    }
  }
})

5、xml渲染

博客网站需要一个sitemap网站地图,用于搜索引擎收录,再弄一个RSS订阅,这些都需要生成XML。

方案一:使用nuxt的sitemap插件,生成静态sitemap.xml文件

https://www.npmjs.com/package/@nuxtjs/sitemap

方案二:

使用thinkjs的View视图功能,通过nunjucks动态渲染xml

https://thinkjs.org/zh-cn/doc/3.0/view.html

server 控制器 controller/front/xml.js

module.exports = class extends think.Controller {
  // sitemap地图
  async sitemapAction() {
    const baseurl = 'https://www.timelessq.com'
    this.assign('siteurl', baseurl);

    const categories = []; // 所有的栏目
    const sitemapList = []; // 所有的文章
    this.assign('list', sitemapList);

    const lastmod = sitemapList.length ? sitemapList[0].updatetime : think.datetime(new Date(), 'YYYY-MM-DD');
    this.assign('lastmod', lastmod);

    const filterCategory = categories.filter(item => !item.link);
    const targetCategory = filterCategory.map(item => {
      const { id, url, level } = item;
      const rows = sitemapList.filter(element => element.category_id === id);
      let lastmod;
      if (rows.length) {
        rows.sort((a, b) => new Date(b.updatetime) - new Date(a.updatetime));
        lastmod = rows[0].updatetime;
      }
      return {
        url: `${baseurl}${url}`,
        lastmod: lastmod || think.datetime(new Date(), 'YYYY-MM-DD'),
        priority: level === 1 ? 0.9 : (level === 2 ? 0.8 : 0.7)
      };
    });
    this.assign('categoryList', targetCategory);

    this.ctx.type = 'text/xml';
    return super.display('home/sitemap.xml');
  }
}

模板文件 view/home/sitemap.xml

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>{$ siteurl $}</loc>
    <lastmod>{$ lastmod $}</lastmod>
    <priority>1.0</priority>
    <changefreq>weekly</changefreq>
  </url>
  {% for item in categoryList %}
  <url>
    <loc>{$ item.url $}</loc>
    <lastmod>{$ item.lastmod $}</lastmod>
    <priority>{$ item.priority $}</priority>
    <changefreq>weekly</changefreq>
  </url>
  {% endfor %}
  {% for item in list %}
  <url>
    <loc>{$ item.url $}</loc>
    <lastmod>{$ item.updatetime $}</lastmod>
    <priority>{$ item.priority $}</priority>
    <changefreq>weekly</changefreq>
  </url>
  {% endfor %}
</urlset>

RSS类似

推荐阅读

恰饭区

评论区 0

0/500

还没有评论,快来抢第一吧