【珍惜時間】vue.news
哈哈好久不見,我們一起來欣賞程式碼呀
老規矩,放一下博主大大的github地址:https://github.com/daoket/vue.news
接下來我們來看看效果呀
接下來我們來一起看看程式碼呀
其實看了動圖,我有幾個想知道的實現的點,1.點選載入更多,2.中間部分的切換,如果有很多的UI,也可以實現很美好的效果呢3.然後就是側邊欄的
接下來我們一起看程式碼呀
我們在main.js中可以看到,專案是有使用懶載入的
//main.js import Vue from 'vue' import App from './App' import router from './router' import './style/public.css' import axios from 'axios' // 處理http請求 import store from './store' // 狀態管理 import VueLazyload from 'vue-lazyload' // 懶載入 /** * @desc 懶載入配置 * @author wtniu */ Vue.use(VueLazyload, { preLoad: 1.3, error: './assets/error.jpg', loading: './assets/loading.gif', attempt: 1 }) Vue.prototype.$axios = axios // 去掉開發環境列印資訊 Vue.config.productionTip = false Vue.config.devtools = false /* eslint-disable no-new */ new Vue({ el: '#app', router, store, render: h => h(App) })
然後我們看看app.vue吧
app.vue中是比較有意思的,引用了四個元件,頭部,底部中間部分以及側邊的
//app.vue <template> <div id="app"> <app-menu></app-menu> <div class="page"> <app-head></app-head> <app-nav></app-nav> <!--keep-alive 切換路不會觸發mounted--> <keep-alive><router-view></router-view></keep-alive> <app-foot></app-foot> </div> </div> </template> <script> import AppHead from './components/public/Head' import AppMenu from './components/public/Menu' import AppNav from './components/public/Nav' import AppFoot from './components/public/Foot' export default { name: 'app', components: { 'app-head': AppHead, 'app-menu': AppMenu, 'app-nav': AppNav, 'app-foot': AppFoot } } </script> <style> #app{ overflow: hidden; } .page{ position: relative; z-index: 99; transition: all 0.5s; } .toggle{ transform: translateX(-120px); } </style>
我們先看頭部和底部的,感覺很好寫的
先看footer啦
//foot.vue <template> <footer class="foot"> <img src="../../assets/head/logo.png"/> <div class="email"> <p>聯絡我:[email protected]</p> <a href="https://github.com/daoket/vue.news"><p>Fork me on GitHub</p></a> </div> </footer> </template> <style lang="scss"> .foot{ height: 100px; background-color: #262627; display: flex; color: #fff; justify-content: space-around; align-items: center; img{ height: 20px; margin-left: 10%; padding-right: 5%; border-right: 1px solid #666; } .email{ font-size: 13px; p{ margin: 10px 0; } } } </style>
其實head部分我認為內容很少的,怎麼感覺程式碼超出了自己的認知
作者大大寫的時候,把右邊menu,點選關閉和展示,是寫在了store裡面,然後還有回到首頁的功能,不過我好像沒有看到搜尋的功能
後面看程式碼的時候發現是作者大大自己註釋了
//head.vue
<template>
<header class="head">
<a href="javascript: void(0)"><img class="vNews" @click="goHome" src="../../assets/head/logo.png"/></a>
<svg class="icon searchBtn" @click='openSearch' aria-hidden="true">
<use xlink:href="#icon-sousuo"></use>
</svg>
<div class="searchPage">
<div class="header">
<div class="search">
<input v-model='searchContent' type="text" />
<svg class="icon" @click='searchNewsBtn' aria-hidden="true">
<use xlink:href="#icon-sousuo"></use>
</svg>
</div>
<svg class="icon close" @click='closeSearch' aria-hidden="true">
<use xlink:href="#icon-hao"></use>
</svg>
</div>
<div class="content">
<p class="today">今天</p>
<ul class="news">
<li ref='newsItem' v-for='(news, index) in searchNews' :key='index'>
<a :href="'#' + news.id" @click='goNews'>
<p v-if='+index < 3'><i class="isTop3"> {{index + 1}} </i><span ref='title' class="title"> {{news.title}}</span></p>
<p v-else><i> {{index + 1}} </i><span ref='title' class="title"> {{news.title}}</span></p>
</a>
</li>
</ul>
</div>
</div>
<div class="aside" @click='toggleMenu'>
<div v-for='i in 3' :key='i' class="line"></div>
</div>
</header>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'apphead', // Do not use built-in or reserved HTML elements as component id
data () {
return {
imgs: [],
searchContent: ''
}
},
computed: {
...mapState({
searchNews: state => state.SelectStore.searchNews
})
},
watch: {
searchContent (curVal) {
if (curVal === '') {
this.$refs.newsItem.map((item) => {
item.style.display = 'block'
item.className = ''
})
}
if (curVal !== '') {
this.$refs.title.map((item) => {
if (item.innerText.match(curVal)) {
item.parentNode.parentNode.parentNode.className = 'hightColor'
} else {
item.parentNode.parentNode.parentNode.style.display = 'none'
}
})
}
}
},
methods: {
setClass (classname) {
return classname
},
setSrc (src) {
return src
},
searchNewsBtn () {
console.log('..searchNewsBtn..')
alert('搜尋完成')
},
goNews () {
console.log('goNews..')
this.closeSearch()
this.clearSearchContent()
},
goHome () {
console.log('goHome..goHome')
this.$router.push('/select')
},
clearSearchContent () {
this.searchContent = ''
},
...mapMutations([
'toggleMenu', 'openSearch', 'closeSearch'
])
}
}
</script>
<style lang="scss">
.head{
height: 60px;
background: #262627;
position: relative;
img{
height: 50px;
position: absolute;
top: 5px;
right: 20%;
cursor: pointer;
}
.vNews{
height: 20px;
top: 20px;
left: 10px;
}
.baidu{
right: 30%;
}
.searchBtn{
cursor: pointer;
color: #FFFFFF;
position: absolute;
top: 18px;
right: 15%;
}
.aside{
height: 60px;
width: 60px;
cursor: pointer;
position: absolute;
top: 0;
right: 0;
padding-top: 1px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
.line{
height: 1px;
width: 25px;
background: #fff;
transition: all 0.5s;
}
.line:nth-of-type(2){
margin: 6px 0;
}
}
.closeMenu{
.line:first-child{
transform: rotate(45deg);
}
.line:nth-child(2){
display: none;
}
.line:last-child{
transform: rotate(-45deg);
}
}
.searchPage{
display: none;//隱藏了搜尋的功能
position: fixed;
height: 100%;
width: 100%;
overflow: scroll;
background: #fff;
z-index: 999;
.header{
height: 60px;
display: flex;
justify-content: space-around;
align-items: center;
padding: 0 2%;
background: #262627;
.search{
height: 40px;
width: 85%;
border: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
input{
height: 40px;
width: 82%;
color: #FFFFFF;
text-indent: 10px;
background-color: #262627;
outline: none;
}
.icon{
color: #FFFFFF;
margin-right: 5%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
}
.close{
height: 30px;
width: 30px;
color: #FFFFFF;
}
}
}
.content{
overflow: hidden;
background-color: #FFFFFF;
.today{
height: 25px;
background: #E3E4EE;
line-height: 25px;
text-indent: 15px;
font-size: 14px;
}
.news li{
font-size: 16px;
margin: 15px;
p{
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
i{
font-size: 16px;
font-style: normal;
margin-right: 10px;
}
i.isTop3{
color: red;
}
span{
width: 90%;
display: inline-block;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
.hightColor{
color: #FFFFFF;
background-color: #EEEEEE;
}
}
</style>
/**
* @desc 顯示隱藏右側選單
*/
export default {
mutations: {
toggleMenu () {
var page = document.querySelector('#app .page')
var aside = document.querySelector('.head .aside')
var pageClass = page.className
var asideClass = aside.className
if (pageClass === 'page') {
page.className = 'page toggle'
} else {
page.className = 'page'
}
if (asideClass === 'aside') {
aside.className = 'aside closeMenu'
} else {
aside.className = 'aside'
}
},
openSearch () {
alert('11')
var searchPage = document.querySelector('.head .searchPage')
searchPage.style.display = 'block'
},
closeSearch () {
console.log('2222')
var searchPage = document.querySelector('.head .searchPage')
searchPage.style.display = 'none'
}
}
}
接下來我們來看app-menu元件
//menu.vue
<template>
<section class="menus">
<p class="user" title="">{{userName}}</p>
<ul class="aside">
<li v-for='(m, index) in menus' :key='index'><a href="">{{m.text}}</a></li>
</ul>
</section>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
userName: state => state.MenuStore.userName,
menus: state => state.MenuStore.menus
})
}
}
</script>
<style lang="scss">
.menus{
position: fixed;
top: 0;
right: 0;
color: #fff;
width: 120px;
height: 100%;
background: #3C3C3D;
z-index: 9;
.user{
height: 60px;
line-height: 60px;
background: #000;
text-align: center;
width: 60%;
padding: 0 20%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.aside li{
height: 50px;
width: 60%;
padding: 0 20%;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
a{
height: 100%;
color: #FFFFFF;
line-height: 50px;
display: inline-block;
}
}
.aside li:hover{
background-color: #3E90E3;
}
}
</style>
這個menus值也是在store中儲存的
//menuStore.js
/**
* @desc 右側選單資料
*/
export default {
state: {
userName: '京州市委書記李達康',
menus: [{
text: '巨頭'
}, {
text: '人物'
}, {
text: '電商'
}, {
text: '創投'
}, {
text: '智慧硬體'
}, {
text: '網際網路+'
}, {
text: 'P2P'
}, {
text: '前沿技術'
}, {
text: '遊戲'
}]
}
}
接下來我們看nav.vue中
//nav.vue
<template>
<section class="nav">
<!--v-for遍歷路由-->
<div class="nav" v-for='(m, index) in menus' :key='index'>
<router-link :to='setPaht(m.path)'><span>{{m.text}}</span></router-link>
</div>
</section>
</template>
<script>
export default {
data () {
return {
// 路由引數
menus: [{
text: '精選',
path: '/select'
}, {
text: '話題',
path: '/point'
}, {
text: '作者',
path: '/author'
}]
}
},
methods: {
setPaht (path) {
return path
}
}
}
</script>
<style lang="scss">
.nav{
width: 100%;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
background: #fff;
.nav{
width: 33%;
height: 100%;
a{
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
text-decoration: none;
color: #666;
font-size: 18px;
text-align: center;
span:first-child{
height: 30px;
width: 100%;
line-height: 30px;
}
}
}
div:nth-child(2) > a > span{
border-left: 1px solid #eee;
border-right: 1px solid #eee;
}
.active{
border-bottom: 1px solid red;
box-sizing: border-box;
}
}
</style>
接下來我們看select.vue
<template>
<div class="select">
<div class="banner">
<swiper :options="swiperOption" ref="mySwiper">
<!-- 這部分放你要渲染的那些內容 -->
<swiper-slide v-for='img in banners' :key="img.channelId">
<img :src="setBannerSrc(img)"/>
</swiper-slide>
<!-- 這是輪播的小圓點 -->
<div v-show='loadBtn' class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
<!--載入動畫-->
<div class="spinner" v-show='loadAnimation'></div>
<transition name='fade' mode='out-in'>
<svg v-show='rocket' class="icon goTop" @click='goPageTop' aria-hidden="true">
<use xlink:href="#icon-0028"></use>
</svg>
</transition>
<section class="news">
<div v-if='requestStatus'>
<div v-for='(news, index) in newsDate' :key='index' :id="news.id">
<a href="javascript: void(0)" class="new" :key='news.channelId'>
<img v-lazy='news.imageurls[0].url' :src="setNewSrc(news.imageurls[0].url)"/>
<div class="intro">
<h4>{{news.title}}</h4>
<p><span>{{news.source}}</span> | <span>{{news.pubDate}}</span></p>
</div>
</a>
</div>
<button class="loadMore" @click='loadMoreBtn' v-show='loadBtn'>點選載入更多</button>
</div>
<div class="fail" v-else>/(ㄒoㄒ)/~~, 請求到資料失敗!</div>
</section>
</div>
</template>
<script>
// 匯入輪播圖元件
import { swiper, swiperSlide } from 'vue-awesome-swiper'
// 匯入vuex
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
data () {
return {
rocket: false,
requestStatus: true,
swiperOption: {
pagination: '.swiper-pagination',
slidesPerView: 'auto',
centeredSlides: true,
paginationClickable: true,
spaceBetween: 30,
onSlideChangeEnd: swiper => {
// 這個位置放swiper的回撥方法
this.page = swiper.realIndex + 1
this.index = swiper.realIndex
}
}
}
},
computed: {
/**
* @desc 從store中引入需要的資料
*/
...mapState({
page: state => state.SelectStore.page,
newsUrl: state => state.SelectStore.newsUrl,
banners: state => state.SelectStore.banners,
newsDate: state => state.SelectStore.newsDate,
loadBtn: state => state.SelectStore.loadBtn,
pathName: state => state.SelectStore.pathName,
loadAnimation: state => state.SelectStore.loadAnimation
})
},
created: function () {
this.askNews(this.newsUrl + this.page) // 第一次載入請求資料
let _this = this
/**
* @desc 判斷是否顯示回到頂部的火箭圖示
*/
window.onscroll = function () {
let leaveTop = document.body.scrollTop
if (leaveTop > 600) {
_this.rocket = true
} else {
_this.rocket = false
}
}
console.log(`%c ${this.$store.state.slogan}`,"font-size: 22px;color:#00BBEE", "Copyright © 2019");
},
methods: {
...mapActions([
'askNews', 'setSrc'
]),
...mapMutations([
'loadMore'
]),
/**
* @desc 設定輪播圖地址
*/
setBannerSrc (src) {
return src
},
/**
* @desc 設定新聞圖片地址
*/
setNewSrc (url) {
return url
},
/**
* @desc 載入更多
*/
loadMoreBtn () {
this.loadMore()
this.askNews(this.newsUrl + this.page)
},
/**
* @desc 回到頂部
*/
goPageTop () {
document.body.scrollTop = 0
}
},
components: {
swiper,
swiperSlide
}
}
</script>
<style lang="scss">
.select{
background: #fff;
.swiper-wrapper{
height: 200px;
.swiper-slide img{
width: 100%;
height: 200px;
}
}
.news{
min-height: 500px;
padding: 0 10px;
.new{
height: 100px;
color: #262627;
border-bottom: 1px solid #eee;
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
img{
height: 80px;
width: 100px;
}
.intro{
width: 80%;
height: 80px;
display: flex;
padding-left: 10px;
flex-direction: column;
justify-content: space-between;
h4{
font-size: 20px;
line-height: 1.2;
font-weight: bold;
overflow: hidden;
display: -webkit-box;
word-break: break-all;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
}
p{
font-size: 13px;
color: #666;
}
}
}
.loadMore{
height: 50px;
width: 100%;
color: #545454;
background: #eee;
text-align: center;
line-height: 50px;
font-size: 13px;
border: none;
border-radius: 0;
outline: none;
margin-bottom: 10px;
}
.fail{
display: flex;
min-height: 300px;
align-items: center;
justify-content: center;
}
}
}
/*載入動畫*/
.spinner {
position: fixed;
left: 40%;
bottom: 10%;
width: 80px;
height: 80px;
margin: 50px auto;
background-color: #69C61D;
border-radius: 100%;
-webkit-animation: scaleout 1.0s infinite ease-in-out;
animation: scaleout 1.0s infinite ease-in-out;
}
@-webkit-keyframes scaleout {
0% { -webkit-transform: scale(0.0) }
100% {
-webkit-transform: scale(1.0);
opacity: 0;
}
}
@keyframes scaleout {
0% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 100% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
opacity: 0;
}
}
.goTop{
color: #50BFFF;
position: fixed;
bottom: 40px;
right: 20px;
z-index: 9999;
cursor: pointer;
width: 60px;
height: 60px;
transition: all 1s ease;
transform: scale(0.6);
}
.goTop:active{
color: #C40000;
transform: scale(1);
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.8s
}
.fade-enter, .fade-leave-active {
opacity: 0
}
.tip{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
a{
color: #19C8A9;
}
span{
margin-bottom: 10px;
}
}
</style>
載入更多的程式碼也有在store中定義
//selectStore.js
import axios from 'axios'
import $ from 'webpack-zepto'
export default {
state: {
page: 1,
data: [],
newsDate: [],
banners: [],
searchNews: [],
loadBtn: false,
loadAnimation: true,
newsUrl: 'https://route.showapi.com/109-35?showapi_appid=34477&showapi_sign=cfa5957a730f43d38886bd16469b2a86&channelId=5572a108b3cdc86cf39001cd&needContent=0&needHtml=1&page='
},
mutations: {
/**
* @desc 載入新聞
*/
loadNews (state) {
let data = state.data
if (data.length > 2) { // 判斷資料是否存在
for (var i = 0; i < data.length; i++) {
if (data[i].imageurls[0]) {
state.newsDate.push(data[i])
}
}
for (let i = 0; i < 4; i++) {
if (state.banners.length < 4) {
state.banners.push(state.newsDate[i].imageurls[0].url)
}
}
} else {
state.loadAnimation = false
console.log('沒有更多資料了')
return false
}
// 資料請求成功顯示載入更多按鈕
state.loadBtn = true
state.loadAnimation = false
},
/**
* @desc 點選載入更多
*/
loadMore (state) {
state.page++
state.loadAnimation = true
},
updatePathName (state, newPathName) {
state.pathName = newPathName
}
},
actions: {
/**
* @desc axios非同步請求函式 類似jquery的ajax方法
*/
askNews ({commit, state}, url) {
axios({
method: 'get',
url: url
})
.then((res) => {
if (res.data.showapi_res_code !== -2) {
let data = res.data.showapi_res_body.pagebean.contentlist
state.data = data
for (let i in data) {
state.searchNews.push({title: data[i].title, id: data[i].id})
}
} else {
var tips = `<p class="tip">
<span>介面請求已達上限 /(ㄒoㄒ)/~~!!!</span>
<span>選擇和AI聊天,緩解失望的心情吧:</span>
<a href="http://lx.openspeech.cn/auth/project/ai_niu/index.html">快來和我聊天!</a>
</p>`
$(tips).appendTo('.news')
}
commit('loadNews')
})
}
}
}
接下來看話題頁面
其實我很好奇,為什麼把資料寫在store中
//pointStore.js
/**
* @desc 話題頁面資料
*/
export default {
state: {
points: [{
times: '609期',
title: '提高個稅起徵點真能減負嘛?',
msg: '3月7日,財政部部長肖捷在釋出會上表示,個人所得稅免徵額將根據消費水平綜合測算,...'
}, {
times: '609期',
title: '提高個稅起徵點真能減負嘛?',
msg: '3月7日,財政部部長肖捷在釋出會上表示,個人所得稅免徵額將根據消費水平綜合測算,...'
}, {
times: '609期',
title: '提高個稅起徵點真能減負嘛?',
msg: '3月7日,財政部部長肖捷在釋出會上表示,個人所得稅免徵額將根據消費水平綜合測算,...'
}]
}
}
<template>
<section class="point">
<div class='question'>
<div class="mask">
<h2>熱點城市房價會否持續瘋漲?</h2>
<p>610期</p>
<div class="result">
<p><span>正方</span><span>反方</span></p>
<progress value="75" max="100"></progress>
<p><span>75%</span><span>25%</span></p>
</div>
<a class="join" href="javascript: void(0)">進入專題></a>
</div>
</div>
<div class="prev">
<div v-for='(p, index) in points' :key='index' class="list">
<div class="mask">
<span class="times">{{p.times}}</span>
<h2>{{p.title}}</h2>
<p>{{p.msg}}</p>
<a class="join" href="javascript: void(0)"> > </a>
</div>
</div>
</div>
</section>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'point',
computed: {
...mapState({
points: state => state.PointStore.points
})
}
}
</script>
<style lang="scss">
.point{
color: #fff;
background: #fff;
.question{
height: 180px;
background: url(../assets/point/pointBg.jpg);
background-size: 100% 100%;
.mask{
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
height: 100%;
width: 100%;
position: relative;
background: rgba(0,0,0,0.6);
h2{
font-size: 20px;
font-weight: bold;
}
p{
font-size: 16px;
margin: 10px 0;
}
.result{
height: 100px;
width: 80%;
p{
display: flex;
justify-content: space-between;
}
progress {
width: 100%;
background-color:#005588;
color: #E94C3D; /*IE10*/
}
progress::-moz-progress-bar { background: #E94C3D; }
progress::-webkit-progress-bar { background: #005588; }
progress::-webkit-progress-value { background: #E94C3D; }
}
.join{
color: #E94C3D;
position: absolute;
bottom: 10px;
right: 10px;
}
}
}
.prev{
padding: 10px;
.list{
height: 150px;
width: 100%;
margin-bottom: 10px;
overflow: hidden;
background: url(../assets/point/pointBg.jpg) no-repeat;
background-size: 100%;
.mask{
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
height: 100%;
width: 100%;
background: rgba(0,0,0,0.6);
position: relative;
h2{
font-size: 20px;
font-weight: bold;
width: 100%;
text-align: center;
padding: 0 20px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
p{
color: #eee;
margin: 10px 20px;
line-height: 1.3;
font-size: 13px;
overflow: hidden;
display: -webkit-box;
word-break: break-all;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
}
.times{
position: absolute;
left: 0;
top: 0;
color: #eee;
display: inline-block;
padding: 2px;
font-size: 13px;
}
.join{
position: absolute;
right: 5px;
bottom: 0;
color: #eee;
color: #E94C3D;
display: inline-block;
padding: 10px;
font-size: 13px;
}
}
}
}
}
</style>
接下來是author頁面
<template>
<section class="author">
<button class="goHome" @click='goHome'>Home</button>
<!--<a v-link="select">select</a>-->
<div class="banner">
<div v-for='(a, index) in author' :key='index' class="item">
<div class="msg">
<img :src="setAutherSrc(a.src)"/>
<p class="name">{{a.name}}</p>
<p class="slogan">{{a.slogan}}</p>
</div>
<span class="focus" v-if='a.status' @click='a.status = !a.status'>關注</span>
<span class="focus focused" @click='a.status = !a.status' v-else>已關注</span>
</div>
</div>
<section class="more">
<div v-for='(o, index) in other' :key='index' class="other">
<div class="authorMsg">
<img :src="setOtherSrc(o.src)"/>
<div class="intro">
<p class="name">{{o.name}}</p>
<p class="slogan">{{o.slogan}}</p>
</div>
</div>
<div>
<span class="focus" v-if='o.status' @click='o.status = !o.status' >關注</span>
<span class="focus focused" @click='o.status = !o.status' v-else>已關注</span>
</div>
</div>
</section>
</section>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'author',
computed: {
...mapState({
author: state => state.AuthorStore.author,
other: state => state.AuthorStore.other,
pathName: state => state.SelectStore.pathName
})
},
watch: {
'$route': 'fetchData'
},
methods: {
setAutherSrc (src) {
return src
},
setOtherSrc (src) {
return src
},
fetchData () {
location.hash = 'select'
console.log(this.$route)
},
goHome () {
if (history.length) {
this.$router.go(parseFloat(-this.$store.state.historyLength) + 1)
}
}
},
beforeRouteEnter (to, from, next) {
next()
},
beforeRouteUpdate (to, from, next) {
console.log(9)
next()
},
beforeRouteLeave (to, from, next) {
next()
}
}
</script>
<style lang="scss">
.author{
background: #fff;
border-right: 1px solid #666;
.banner{
background: url(../assets/author/author_banner_bg.jpg);
.item{
height: 210px;
width: 45%;
margin: 2%;
color: #fff;
opacity: 0.9;
display: inline-block;
text-align: center;
background: #2E2E2F;
.msg{
display: flex;
flex-direction: column;
background: #262627;
padding: 10px 0;
justify-content: space-around;
align-items: center;
img{
height: 100px;
width: 100px;
border-radius: 50%;
}
.name{
margin: 10px 0;
}
.slogan{
color: #666;
width: 80%;
font-size: 13px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.focus{
width: 80px;
font-size: 13px;
display: inline-block;
padding: 4px 0;
background: #E94C3D;
border-radius: 10px;
cursor: pointer;
margin: 10px 0;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.focused{
background: #262627;
}
}
}
.more{
padding: 10px;
.other{
height: 100px;
background: #eee;
display: flex;
margin-bottom: 10px;
justify-content: space-between;
padding: 0 10px;
align-items: center;
.authorMsg{
display: flex;
justify-content: space-between;
align-items: center;
img{
height: 80px;
width: 80px;
border-radius: 50%;
}
.intro{
height: 40px;
margin: 0 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
.slogan{
font-size: 13px;
color: #666;
}
}
}
.focus{
display: inline-block;
width: 80px;
color: #fff;
cursor: pointer;
font-size: 13px;
text-align: center;
padding: 5px 0;
background: #D5483A;
border-radius: 15px;
margin-left: 10px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.focused{
background: #262627;
}
}
}
.goHome{
position: fixed;
right: 15px;
bottom: 30px;
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
outline: none;
color: #FFFFFF;
background: rgba(0,0,0,0.5);
}
}
</style>
AuthorStore.js中進入到對應的頁面也是在state中
//authodStore.js
/**
* @desc 作者頁面資料
*/
export default {
state: {
author: [{
src: require('../assets/author/author.jpg'),
name: '變革家',
slogan: '幫股權投資者把好第一關!',
status: true
}, {
src: require('../assets/author/author.jpg'),
name: '懂懂筆記',
slogan: '20年國內財經媒體從業記錄者!',
status: true
}, {
src: require('../assets/author/author.jpg'),
name: '變革家',
slogan: '幫股權投資者把好第一關!',
status: true
}, {
src: require('../assets/author/author.jpg'),
name: '娛樂硬糖',
slogan: '有溫度的泛娛樂產業自媒體。!',
status: true
}],
other: [{
src: require('../assets/author/author.jpg'),
name: '鄺新華',
slogan: '新週刊主筆',
status: true
}, {
src: require('../assets/author/author.jpg'),
name: '40秒',
slogan: '認識最瘋狂的天才',
status: true
}, {
src: require('../assets/author/author.jpg'),
name: '艾問iAsk',
slogan: '科技商業價值發現者',
status: true
}]
}
}
最後就是router.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '../store'
import Select from '../components/Select'
import Point from '../components/Point'
import Author from '../components/Author'
Vue.use(Router)
const router = new Router({
linkActiveClass: 'active',
hashbang: true, // 將路徑格式化為#!開頭
history: true, // 啟用HTML5 history模式,可以使用pushState和replaceState來管理記錄
/**
* @desc 路由配置
*/
routes: [
{
path: '/select',
component: Select
}, {
path: '/point',
component: Point
}, {
path: '/author',
component: Author,
meta: { requiresAuth: true }
}, {
path: '/*',
component: Select
}
]
})
/**
* @desc 全域性監聽路由變化
*/
router.beforeEach((to, from, next) => {
store.dispatch('updateHistoryLength') // 變化時更新路由切換長度
next()
})
export default router
其實不太理解作者寫的這個路由的切換次數
···js
/**
- @desc 匯入需要的store
- @author wtniu
*/
import Vue from 'vue'
import Vuex from 'vuex'
import SelectStore from './SelectStore'
import PointStore from './PointStore'
import AuthorStore from './AuthorStore'
import MenuStore from './MenuStore'
import HeadStore from './HeadStore'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
slogan: '叩首為夢 碼夢為生!',
historyLength: 0
},
mutations: {
/*
* @desc 記錄路由切換次數
* @arg {object} state 狀態
*/
updateHistoryLength (state) {
state.historyLength++
}
},
actions: {
updateHistoryLength ({commit}) {
commit('updateHistoryLength')
}
},
modules: {
SelectStore,
PointStore,
AuthorStore,
MenuStore,
HeadStore
}
})
作者大大的這樣專案很值得推薦的,將資料放在store的state中這種方法很很新穎,很喜歡,推薦