preface
This NuxT-Blog project is built based on NUxT server rendering (SSR)
rendering
See sdjblog.cn for the full effect
Functional description
Implemented functions
- Log in
- The article lists
- link
- Comments like this article
- The article archive
- A list of items
- The message list
- Kanban girl background
Technology library dependency
- Nuxtjs /axios (API request)
- @nuxtjs/style-resources (SCSS public file introduction)
- Element-ui (Component Library)
- Highlight.js (code highlighting)
- Moment (Time format processing)
- Nprogress (Progress bar)
- Nuxt (Vue framework)
The project structure
- Assets resource file (image, CSS and font icon) - Components - RaindropCanvas Rain Effects - BackTop Back to top - EmptyShow empty state - HeaderNav head navigation - MyForm SideBar - TagBox - Layouts - Pages - Article - Page - _num Article list - archive - Project Articledetail-_id - article list header and sidebar - index Default home page route - Message list - Plugins package - static Kanban.com, background resources, etc Store Vuex state management - utils Form verification, title directory navigation, time formatting and other common methods encapsulation - nuxt.config Personalized configurationCopy the code
The sidebar
-
Get the corresponding inspirational statement display by week
-
Related contact information, such as Github, code cloud, background login page and nuggets, etc
-
Filter the list of articles by article tag and article sorting
-
Link display
The article archive
Article list formatting, merge the same month data content in the list data into a new array, and regenerate the month list data
async asyncData({ $axios }) {
const res = await $axios.get('/blogPage/statistics/articleArchive')
let total = res.data.length
let data = res.data
let arr = []
let articleList = []
if(data.length > 0){
data.forEach(item= >{
let outerObj = { month: item._id.month, articleArr: []}let inObj = { articleId: item._id.id, title: item._id.title, createTime: item._id.createTime}
outerObj.articleArr.push(inObj);
arr.push(outerObj);
})
let newData = []; // Target array
let newObj = {};
arr.forEach((item, index) = > {
if(! newObj[item.month]) { newData.push(item); newObj[item.month] =true;
} else {
newData.forEach(data= > {
if (data.month === item.month) {
data.articleArr = [...data.articleArr, ...item.articleArr]
}
})
}
})
articleList = newData
}
return { articleList, total }
}
Copy the code
The article details
Add class to the content H title tag and extract the title generation directory
// Add class to the title
export function catalogList(content) {
// remove marked parsing generates the ID in the h header tag
// content = content.replace(/(\sid\s*=[\s\'\"].*? [\s\'\"])/g,"")
const toc = content.match(/<[hH][1-6]>.*? <\/[hH][1-6]>/g)
let tocList = null
if (toc && toc.length > 0) {
toc.forEach((item, index) = > {
let _toc = `<div class='rich-title' id='content-title${index}'>${item} </div>`
content = content.replace(item, _toc)
})
tocList = toToc(toc)
}else{
tocList = '
directory (none)
\n'
}
let obj = {
tocList,
content
}
return obj
}
// The article content h tag generates the title directory
function toToc(data) {
let levelStack = []
let result = '
directory
\n'
const addStartList = () = > { result += `<div class="catalog-list">\n`; }
const addEndList = () = > { result += '</div>\n'; }
const addLInk = (index, itemText) = > { result += `<div class='catalog-link' title='${itemText}' id='title${index}'>${itemText}</div>\n`; }
data.forEach(function (item, index) {
let itemText = item.replace(/<[^>]+>/g.' ') // Matches the text in the h tag
let itemLabel = item.match(/<\w+? >/) [0] / / match h? Tag < h? >
let levelIndex = levelStack.indexOf(itemLabel) // Check whether
?>
label, ul and LI are added
?>
if (levelIndex === -1) {
levelStack.unshift(itemLabel)
addStartList()
addLInk(index, itemText)
}
tag, and put li directly under this ul at the top of the stack
?>
else if (levelIndex === 0) {
addLInk(index, itemText)
}
tag, but not at the top of the stack, requires that all previous
?>
else {
while (levelIndex--) {
levelStack.shift()
addEndList()
}
addLInk(index, itemText)
}
})
// If there is
while (levelStack.length) {
levelStack.shift()
addEndList()
}
return result
}
Copy the code
Click the TAB directory to jump to the corresponding location and scroll to the listening location to highlight the title
//rich-title Specifies the class to be added to the content title
this.$nextTick(() = >{
let linkArr = document.querySelectorAll(".rich-title")
let linkTopArr = []
if(linkArr.length > 0){
linkArr.forEach(item= >{
linkTopArr.push(item.offsetTop - 130)
})
linkTopArr.push(2 * linkTopArr[linkTopArr.length-1])
this.linkTopArr = linkTopArr
}
window.addEventListener('scroll'.this.handleScroll, true)})// Scroll listener
handleScroll(){
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
let {linkTopArr} = this
const linkArr = document.querySelectorAll(".catalog-link")
if(linkArr.length > 0) {for(let i = 0; i < linkTopArr.length; i++){
let start = linkTopArr[i]
let top = linkTopArr[i + 1]
if (scrollTop >= start && scrollTop <= top) {
// Get the target element to scroll the article to the directory
linkArr.forEach((item) = > {
item.classList.remove('link-active')})if(linkArr[i]){
linkArr[i].classList.add('link-active')}break; }}}}Copy the code
The message list
Mouse drag message movement, when the drag move to the top, rain effect
// Bind mouse press events<div class="box-item" v-for='item in messageList' :key='item._id' :style="item.style" @mousedown.prevent="mousedown" v-show='initData'></div>
Copy the code
// Drag the message down and hold down the left mouse button
mousedown (e) {
this.isDrag = true
this.dragObj = e.currentTarget
this.dragMouseOffset = this.getCurrentOffset(e)
this.maxDragOffset = this.getMaxDragOffset(e)
this.LiftingZIndex()
document.addEventListener('mousemove'.this.mousemove)
document.addEventListener('mouseup'.this.mouseup)
},
// Mouse distance element position
getCurrentOffset (e) {
let target = e.target
let offset = {
x: 0.y: 0
}
while (target.className.indexOf('box-item') < 0) {
offset = {
x: offset.x + target.offsetLeft + target.clientLeft,
y: offset.y + target.offsetTop + target.clientTop
}
target = target.offsetParent
}
offset = {
x: e.offsetX + offset.x,
y: e.offsetY + offset.y + 60,}return offset
},
/ / to get
getMaxDragOffset (e) {
const target = e.currentTarget
let w = target.offsetWidth,
h = target.offsetHeight
return {
w: this.screen.width - w,
h: this.screen.height - h - 60}},// The current element is upgraded
LiftingZIndex () {
this.noteIndex += 1
this.dragObj.style.zIndex = this.noteIndex
},
mousemove (e) {
if (!this.isDrag) return
let {x, y} = this.getCurrentEleCoords(e)
let {w, h} = this.maxDragOffset
if (x < 0) x = 0
if (x > w) x = w
if (y < 0) y = 0
if (y > h) y = h
this.dragObj.style.left = `${x}px`
this.dragObj.style.top = `${y}px`
if(y <= 0) {this.showRaindropCanvas = true}},// The current mouse distance
getCurrentEleCoords(e){
return {
x: e.clientX - this.dragMouseOffset.x,
y: e.clientY - this.dragMouseOffset.y
}
},
mouseup () {
this.isDrag = false
}
Copy the code
Kanban girl background
By importing resources in nuxt.config.js
Head: {title: 'personal blog ', meta: [{charset:' utF-8 '}, {name: 'viewport', content: 'width=device-width, initial-scale=1'}, {hid: 'keywords', name: 'keywords', content: 'front-end, blog, vue, node'}, {hid: 'description', name: 'description', Content: 'Personal technical blog, vue, node'}], link: [{rel: 'icon', type: 'image/x-icon', href: '/ favicon. Ico'}], script: [{SRC: '/ live2dw/lib/L2Dwidget. Min. Js' / / kanban musume}, {SRC:'/navigator. Js / / device type judgment}, {SRC :'/ bgshow.js ', // body: true}]},Copy the code
// Initialize render in Layout
created() {
if (process.browser) {
setTimeout(() = > {
window.L2Dwidget.init({
pluginRootPath: "/live2dw/".pluginJsPath: "lib/".pluginModelPath: `live2d-widget-model-shizuku/assets/`.tagMode: false.debug: false.model: {
jsonPath: `/live2dw/live2d-widget-model-shizuku/assets/shizuku.model.json`
},
display: {
position: "right".width: 220.height: 400.hOffset: 30.vOffset: -45
},
react: { opacity: 0.7 },
mobile: { show: true },
log: false
});
}, 400); }}Copy the code
instructions
Nuxt, static, nuxt.config.js, and package.json files on the server. Run NPM install to install dependencies. Pm2 start NPM –name “nuxtBlog” — run start to start service, package.json config config port
Building installation
# install dependencies
$ npm install
# Development environment
$ npm run dev
# Package production environment
$ npm run build
$ npm run start
Static packaging
$ npm run generate
Copy the code
Project Address:
Front Desk Presentation: https://gitee.com/sdj_work/blog-page (Vue/Nuxt/ UNI-app)
Management background: https://gitee.com/sdj_work/blog-admin (Vue/React)
Back-end Node: https://gitee.com/sdj_work/blog-node (Express/Koa)
Blog: https://sdjBlog.cn/
Project series:
Vue+Nuxt blog display
Vue+ UniAPP blog display
Vue+ElementUI backstage blog management
Node + KOA + mongodb blog interface development
Node + Express + mongodb blog interface development