【vue】vue-znly
生活随笔
收集整理的這篇文章主要介紹了
【vue】vue-znly
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
老規矩,放下博主的項目地址:https://github.com/wohaiwo/vue-znly
我一直在想給那些開源者取什么名字比較好,怎樣才對得起他們開源項目的精神,后來想想,還是叫博主吧。有的人用語言表達技術,有的人用代碼表達技術。
接下來我們還是來看項目效果吧
我們可以看到這個項目內容還是挺多的,里面缺少一些內容,但是不影響我們研究這個項目
我們看index.html可以發現,這個項目用到了vue和jquery結合做的。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><meta name="keywords" content="今世緣 景區"><meta name="apple-mobile-web-app-capable" content="yes" /><meta name="apple-touch-fullscreen" content="yes"><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="apple-mobile-web-app-capable" content="yes" /><title>今世緣景區歡迎您</title><link rel="shortcut icon" href="/static/logo/favicon.ico" type="image/x-icon" /><meta name="apple-mobile-web-app-status-bar-style" content="black" /><meta name="format-detection"content="telephone=no, email=no" /><meta http-equiv="refresh" content="2000;url=http://www.baidu.com" /></head><body><div id="app"><router-view></router-view></div><script type="text/javascript" src="http://api.map.baidu.com/api?v=1.4"></script><script type="text/javascript" src="../static/lib/js/jquery-3.2.1.slim.min.js"></script></body>
</html> main.js中引入入口文件App.vue
//main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import routes from './router/router.js';
import axios from 'axios';
// 解決30秒延遲問題
import FastClick from 'FastClick';Vue.use(VueRouter); // 加載vue-router插件
Vue.prototype.$http = axios;FastClick.attach(document.body);// 創建 router 實例,然后傳 `routes` 配置
const router = new VueRouter({ mode: 'hash',routes
});// 創建和掛載根實例
var vm = new Vue({router,components: { App }
}).$mount('#app') //app.vue中還加入了動畫
<template><div><transition name="router-fade" mode="out-in"><router-view></router-view></transition></div>
</template><script> import './static/lib/css/main.css'import './static/lib/css/reset.css'export default {}</script><style lang="scss">.router-fade-enter-active, .router-fade-leave-active {transition: opacity .3s;}.router-fade-enter, .router-fade-leave-active {opacity: 0;}.router-slid-enter-active, .router-slid-leave-active {transition: all .4s;}.router-slid-enter, .router-slid-leave-to {transform: translate3d(-100px, 0, 0);opacity: 0;}
</style> router中也是使用懶加載的模式,可以看到首先加載定向的是我們的home組件在app.vue中渲染出來
//router.js
import App from '../App.vue';// Webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中。
const home = resolve => require(['../page/home.vue'], resolve); // 首頁
const introduction = resolve => require(['../page/scenicIntroduction.vue'], resolve);
const listDetail = resolve => require(['../components/listDetail.vue'], resolve);
const travelBox = resolve => require(['../page/travelBox.vue'], resolve);
const externalMap = resolve => require(['../page/externalMap.vue'], resolve);
const service = resolve => require(['../page/service.vue'], resolve);
const dropBox = resolve => require(['../components/dropBox.vue'], resolve);// 定義路由
const routes = [{path: '/',component: App,children: [{path: '/',redirect: { name: 'home' }},{path: '/home',name: 'home',component: home}, {path: '/scenic/introduction', name: 'introduction', component: introduction}, {path: '/scenic/detail/:id/:type/:identifier',name: 'listDetail', component: listDetail}, {path: '/travelBox',name: 'travelBox', component: travelBox}, {path: '/externalMap',name: 'externalMap',component: externalMap}, {path: '/service/:type',name: 'service',component: service}, {path: '/dropBox/:url/:title',name: 'dropBox',component: dropBox}]}
]export default routes; 我們來看home組件,里面的代碼挺有意思的,
先看header組件
//header.vue
<template><header><slot name="logo"></slot><span class="left-icon" v-if="goBack" @click="$router.go(-1)"><i title="返回" class="iconfont"></i></span><span class="left-icon side-bar" v-if="sideBar" @click="showSideBar"><i title="主菜單" class="iconfont"></i></span><span class="title-text" v-if="headTitle">{{headTitle}}</span><transition name="slide-fade"><nav v-show="isShowSideBar"><router-link to="/scenic/introduction"><i class="iconfont"></i>景區介紹</router-link><router-link :to="{name: 'service', params: {type: 3}}"><i class="iconfont"></i>景區公告</router-link><router-link :to="{name: 'service', params: {type: 15}}"><i class="iconfont"></i>景區服務</router-link><router-link :to="{name: 'service', params: {type: 13}}"><i class="iconfont"></i>預訂門票</router-link><router-link :to="{name: 'service', params: {type: 14}}"><i class="iconfont"></i>特色購物</router-link><router-link to="/travelBox"><i class="iconfont"></i>旅行百寶箱</router-link><router-link :to="{name: 'dropBox', params: {url: vrUrl, title: vrTitle}}"><i class="iconfont"></i>虛擬旅游</router-link><router-link :to="{name: 'service', params: {type: 6}}"><i class="iconfont"></i>餐飲住宿</router-link></nav></transition></header>
</template>
<script>export default {data() {return {}},props: ['goBack', 'headTitle', 'sideBar', 'isShowSideBar', 'vrUrl', 'vrTitle'],methods: {// 子組件通過emit向父組件傳遞事件的函數名showSideBar() {this.$emit('breadcrumb');}}}
</script>
<style scoped lang="scss">$nav-color: #e60012;header {position: fixed;left: 0;top: 0;z-index: 100;width: 100%;height: 40px;line-height: 40px;color: $nav-color;background: #fff ;text-align: center;border-bottom: 2px solid #ededed;box-sizing: border-box;span {font-size: 18px;font-weight: bold; } .left-icon {position: absolute;left: 0;top: 50%;width: 50px;transform: translateY(-50%);i {color: $nav-color;}}.side-bar {left: 0;width: 10%;background: $nav-color;i {color: #fff;}}nav {position: fixed;left: 0;right: 0;top: 40px;bottom: 50px;z-index: 20;width: 140px;background: #fff;a {display: block;height: 50px;line-height: 50px;text-align: left;padding-left: 8%;box-sizing: border-box;color: #000;&:not(:last-child) {border-bottom: 1px solid #e6e6e6;}i {color: $nav-color;margin-right: 20px;}}}}.slide-fade-enter-active, .slide-fade-leave-active {transition: all 0.3s ease-in;}.slide-fade-enter, .slide-fade-leave-to{opacity: 0;transform: translate3d(-150px, 0, 0);}// 適配一體機樣式@media screen and (min-width: 1000px) {$header-height: 100px;i {font-size: 36px;}header {font-size: 32px;height: $header-height;line-height: $header-height;border-bottom: 4px solid #ededed;span {font-size: 45px;font-weight: bold; }.left-icon {width: $header-height;}nav {top: $header-height;bottom: $header-height;width: 300px;a {height: $header-height;line-height: $header-height;border-bottom: 3px solid #e6e6e6;}}}}
</style> userCount.vue不知道表達什么意思?
//userCount.vue
//src\components\userCount.vue<template><div><p>{{ msg }}</p></div>
</template><script>export default {data() {return {msg: ''}},created() {let url = '/JSY_H5/h5/statistics';this.$http.get(url).then((response) => {this.$data.msg = response.data.data.msg;}, (response) => {console.log('oops, data is error');});}}
</script><style scoped lang="scss">div {position: relative;width: 100%;height: 20px;padding: 0 4%;margin-top: 40px;font-size: 14px;color: #ddd;background: rgba(0, 0, 0, .4);overflow: hidden;z-index: 40;user-select: none;box-sizing: border-box;p {left: 100%;position: absolute;z-index: 40;white-space: nowrap;animation-delay: 1s;animation-name: slide;animation-duration: 45s;animation-iteration-count: infinite;}}@media screen and (min-width: 1000px) {div{height: 60px;margin-top: 100px;font-size: 32px;p {line-height: 60px;}}}@keyframes slide {0% { left: 100%; }100% { left: -120%; }}
</style> //footer.vue
<template><footer><ul><li><router-link :to="{name: 'service', params: {type: 15}}" :class=" pathName == navUrl[0] ? 'active' : ''"><i class="iconfont"></i><span>景區服務</span></router-link></li><li><router-link to="/home" :class=" pathName == navUrl[1] ? 'active' : ''"><i class="iconfont"></i><span>主頁</span></router-link></li><li><router-link :to="{name: 'service', params: {type: 6}}" :class=" pathName == navUrl[2] ? 'active' : ''"><i class="iconfont"></i><span>餐飲住宿</span></router-link></li></ul></footer>
</template><script>export default {data() {return {isShow: false,navUrl : [0, 1, 2]}},props: ['pathName'],created() {},methods: {showNav(state) {this.$data.isShow = state ? false : true;}}}
</script><style scoped lang="scss">footer {display: block;width: 100%;height: 50px;position: fixed;left: 0;bottom: 0;z-index: 100;color: #000;background: #fff; ul {height: 100%;overflow: hidden;li {display: inline-block;position: relative;float: left;width: 33.33%;height: 100%;box-sizing: border-box;.iconfont {display: block;margin-top: 4px;font-size: 20px;}}}// 菜單欄選中點擊樣式.active {i, span {color: #e60012;}}a {display: block;width: 100%;height: 100%;font-size: 14px;color: #5D656B;text-align: center;}}.slide-fade-enter-active {transition: all .3s ease;}.slide-fade-leave-active {transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);}.slide-fade-enter, .slide-fade-leave-to {transform: translate3d(0, 100%, 0);opacity: 0;}@media screen and (min-width: 1000px) {footer {height: 100px;ul {li {.iconfont {font-size: 48px;}}}a {font-size: 24px;}}}
</style> home.vue引入了這幾個組件
//home.vue
<template><div id="main"><v-header sideBar="true" :isShowSideBar="isShowSideBar" :vrUrl="vRinfo.jumpUrl" :vrTitle="vRinfo.title" @breadcrumb="showSideBar"><span class="header-logo" slot="logo"><img class="logo" :src="logoImgUrl" alt="logo-title"></span></v-header><user-count></user-count><!-- 首頁滾動banner --><div class="banner"><div class="swiper-container" @click="closeSideBar"><div class="swiper-wrapper"><!-- 從后端取數據進行渲染的 --><div class="swiper-slide" v-for="item in imageDataArr"><img :src="item.INFO_IMAGE_URL" :alt="item.INFO_TITLE"></div></div><!-- 如果需要分頁器 --><div class="swiper-pagination swiper-pagination-white"></div></div><nav class="right-side"><router-link :to="{name: 'service', params: {type: 13}}"><span>預訂</span><span>門票</span></router-link><router-link v-if="isApp" :to="{name: 'dropBox', params: {url: vRinfo.jumpUrl, title: vRinfo.title}}"><span>虛擬</span><span>旅游</span></router-link><a v-if="!isApp" target="_blank" :href = "vRinfo.jumpUrl"><span>虛擬</span><span>旅游</span></a><a @click="showSideBar"><span>更多</span><span>功能</span></a></nav></div><v-footer :pathName="1"></v-footer></div>
</template><script>
import Vue from 'vue';
import vHeader from '../components/header'
import userCount from '../components/userCount'
import vFooter from '../components/footer.vue'
import '../static/lib/js/swiper.min.js'
import '../static/lib/css/swiper.min.css'export default {data() {return {isApp: false, // 是否是園區一體機isShowSideBar: false,imageDataArr: [], // 首頁輪播圖vRinfo: { // 虛擬旅游title: '',jumpUrl: ''},logoImgUrl: ''}},components: {vHeader, userCount, vFooter},created() {},mounted() {let isApp = window.localStorage ? localStorage.getItem('isApp') : Cookie.read('isApp');// 瀏覽器本地存儲是否是一體機// 判斷本地緩存里面是否已經存在isAppif(isApp == 'true') {this.logoImgUrl = '../static/logo/logo-red-pc.png';this.isApp = true;} else {// 判斷是否是第一次進來首頁,如果是,則獲取params的參數this.isApp = this.$route.query && this.$route.query.app;if(this.isApp == 'true') {// 保存到全局變量中if(window.localStorage) {localStorage.setItem('isApp', this.isApp);} else {Cookie.wirte('isApp', this.isApp);}this.logoImgUrl = '../static/logo/logo-red-pc.png';} else {this.logoImgUrl = '../static/logo/logo-red-h5.png';}}this.initPage();this.getVRTravel();},methods: {initPage() {let url = `/JSY_H5/h5/queryServiceList?type=1`;this.$http.get(url).then((response) => {this.imageDataArr = response.data.rows;// vue.nextTick在頁面初始掛載就要渲染好輪播Vue.nextTick(function() {new Swiper('.swiper-container', {autoplay: 10000, pagination: '.swiper-pagination',loop: true});});}, (response) => {console.log('oops, data is not found'); });},getVRTravel() {let url = '/JSY_H5/h5/queryServiceList?type=16';this.$http.get(url).then((response) => {// 遍歷數據,改變數據結構,套用同一天模板listTplthis.$data.vRinfo['title'] = response.data.rows[0]['INFO_TITLE'];this.$data.vRinfo['jumpUrl'] = response.data.rows[0]['JUMP_URL'];});}, showSideBar() {this.isShowSideBar = !this.isShowSideBar;console.log("this.isShowBar",this.isShowSideBar)},closeSideBar() {this.isShowSideBar = false;}}
}
</script><style scoped lang="scss">#main {font-family: "Microsoft Yahei", 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;}.header-logo {display: inline-block;width: 100%;height: 40px;box-sizing: border-box;.logo {height: 100%;}}.banner {$right-side-size: 50px;.swiper-container {position: fixed;left: 0;right: 0;top: 40px;bottom: 50px;z-index: 10;overflow: hidden;.swiper-slide img {width: 100%;height: 100%;}}.right-side {position: fixed;right: 4%;bottom: 70px;z-index: 10;width: $right-side-size;a {display: inline-block;width: $right-side-size;height: $right-side-size;color: #fff;background: #e60012;border: 2px solid #fff;padding: 5px;border-radius: 50%;box-shadow: 0 0 10px 0 rgba(0, 0, 0, .5);box-sizing: border-box;span {display: block;font-size: 14px;height: 18px;line-height: 18px;}&:not(:last-child) {margin-bottom: 10px;}}}}// 適配一體機樣式@media screen and (min-width: 1000px) {$right-side-size: 150px;.header-logo {height: 100px;}.banner {.swiper-container {top: 100px;bottom: 100px;}.right-side {right: 4%;bottom: 50%;width: $right-side-size;transform: translate3d(0, 50%, 0);a {width: $right-side-size;height: $right-side-size;padding: 12px;border: 5px solid #fff;span {font-size: 45px;height: 55px;line-height: 55px;}}}}}
</style> 在景區頁面中引入了listTpl.vue
//listTpl.vue
<template><div><div class="list-tpl" ><ul v-if="!isType" class="list-item"><li v-for="item in items"><router-link :to="{name: 'listDetail', params: {id: item.id, type: type, identifier: identifier}}"><div class="list-image"><img :src="item.imageUrl"></div><aside ><h3>{{ item.title }}</h3><article>{{ item.description }}</article></aside></router-link></li></ul><ul v-if="isType" class="list-item"><li v-for="item in items"><div class="list-image"><img :src="item.imageUrl"></div><aside ><h3>{{ item.title }}</h3><article v-html= "item.description"></article><a class="jump-url" v-if="!isApp" :href="item.jumpUrl" target="_blank">去預訂</a><a class="jump-url" v-if="isApp" @click="showQRCode(item.qrCode)">去預訂</a></aside></li></ul></div><div v-if="isShowQrBox" id="qrcode" @click="closeQrcodeBox"><div class="mask"></div><div id="qrcode-content"></div></div></div>
</template><script>import Vue from 'vue';import '../static/lib/js/jquery.qrcode.min.js';export default {data() {return {isApp: false, // 判斷是否使用不同的遍歷模塊, true => 調出二維碼模板isType: false, // 當type = 13 || 14時,顯示去預定的模板isShowQrBox: false}},props: ['identifier', 'items', 'type'],created() {// 在listTpl頁面中 只在預訂門票和特色購物里面調出而二維碼if(this.type == 13 || this.type == 14){this.isType = true;// 判斷是否是園區一體機let isApp = window.localStorage ? localStorage.getItem('isApp') : Cookie.read('isApp');if(isApp == 'true') {this.isApp = true;}}},methods: {showQRCode(url) {this.isShowQrBox = true;jQuery('#qrcode #qrcode-content').empty();Vue.nextTick(function() {jQuery('#qrcode #qrcode-content').qrcode(url);});},// 關閉二維碼框closeQrcodeBox() {this.isShowQrBox = false;}}}
</script>
<style scoped lang="scss">.list-tpl {margin-top: 45px;.list-item {margin: 10px auto;list-style: none;height: 100vh;overflow: auto;background: #EDEDED; li {display: inline-block;width: 100%;padding: 2%;margin-bottom: 10px;overflow: hidden;box-sizing: border-box;background: #fff;a {display:inline-block;}.list-image {float: left;width: 30vw;height: 30vw;margin-right: 3vw;box-sizing: border-box;img {width: 100%;height: 100%; }}aside {position: relative;min-height: 30vw;font-size: 14px;text-align: left;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box;h3 {color: #CD1940;padding: 2px 0 5px 0;font-size: 16px;font-weight: bold;}article {font-size: 14px;color: #000;line-height: 1.4;text-align: justify;}.jump-url {position: absolute;right: 0;bottom: 0;width: 60px;height: 30px;line-height: 30px;text-align: center;color: #FFF;background: #e60012;box-sizing: border-box;}}}}}#qrcode {position: relative;.mask {position: fixed;display: block;left: 0;right: 0;top: 0;bottom: 0;background: rgba(0, 0, 0, 0.4);z-index: 10;}#qrcode-content {position: fixed;left: 50%;top: 50%;padding: 15px;text-align: center;background: #fff;z-index: 100;transform: translate3d(-50%, -50%, 0);&:after {content: '掃一掃上面的二維碼圖案';display: block;padding-top: 10px;}}}@media screen and (min-width: 1000px) {.list-tpl {margin-top: 100px;.list-item {li {aside {h3 {font-size: 38px;}article {font-size: 32px;}.jump-url {position: absolute;right: 0;bottom: 0;width: 120px;height: 60px;line-height: 60px;text-align: center;color: #FFF;font-size: 24px;background: #e60012;box-sizing: border-box;}}}}}}
</style>/#/?app=true 我們其實可以猜測這個組件里面主要是展示景區相關圖片,并且還有二維碼掃碼的功能,用jQuery做的
完整的景區介紹的代碼
<template><div><v-header goBack="true" headTitle="景區介紹"></v-header><list-tpl :items="scenicInfo" :type="type" identifier="1"></list-tpl><loading :show="done"></loading></div>
</template><script>import vHeader from '../components/header.vue';import listTpl from '../components/listTpl.vue';import loading from '../components/loading.vue'; export default {data() {return {done: false,type: '0', // 這個類型應該是字符串,需要跟路由匹配到scenicInfo: []}},components: {vHeader, listTpl, loading},mounted() {// 頁面初始化時加載數據this.initPage();},methods: {initPage() {this.done = true;let url = '/JSY_H5/h5/querySSSList';this.$http.get(url).then((response) => {// 遍歷數據,改變數據結構,套用同一套模板listTplresponse.data.rows.forEach((item, index) => {let tmp = {};tmp['description'] = item['SS_DESCRIPTION'];tmp['id'] = item['SS_NO'];tmp['imageUrl'] = item['SS_IMAGE_URL'];tmp['title'] = item['SS_TITLE'];this.$data.scenicInfo.push(tmp);});this.$data.done = false;}, (response) => {this.$data.done = false;});}}}</script> //loading.vue
<template><transition><svg class="spinner" :class="{ show: show }" v-show="show" width="68px" height="68px" viewBox="0 0 44 44"><circle class="path" fill="none" stroke-width="4" stroke-linecap="round" cx="22" cy="22" r="20"></circle></svg></transition>
</template><script>export default {props: ['show']}
</script><style lang="scss">$offset: 126;$duration: 1.4s;.spinner {position: fixed;z-index: 999;transition: opacity .15s ease;animation: rotator $duration linear infinite;animation-play-state: paused;right: 50%;top: 20%;margin-right: -34px;&.show {animation-play-state: running}&.v-enter, &.v-leave-active {opacity: 0;}&.v-enter-active, &.v-leave {opacity: 1;}}@keyframes rotator {0% {transform: scale(0.5) rotate(0deg);}100% {transform: scale(0.5) rotate(270deg);}}.spinner .path {stroke: #42b983;stroke-dasharray: $offset;stroke-dashoffset: 0;transform-origin: center;animation: dash $duration ease-in-out infinite;}@keyframes dash {0% {stroke-dashoffset: $offset;}50% {stroke-dashoffset: ($offset/2) transform rotate(135deg);}100% {stroke-dashoffset: $offset transform rotate(450deg);}}</style> //src\page\service.vue
<template><div><v-header goBack="true" :headTitle="headTitle"></v-header><list-tpl :items="serviceInfo" :type="type" identifier="2"></list-tpl><v-footer :pathName="index" v-show=" type == 6 || type == 15"></v-footer><loading :show="done"></loading></div>
</template><script>import vHeader from '../components/header.vue';import listTpl from '../components/listTpl.vue';import loading from '../components/loading.vue';import vFooter from '../components/footer.vue';export default {data() {return {type: null,done: false,index: 0, // 動態顯示footer導航欄顯示位置serviceInfo: []}},computed: {headTitle: function() {let type = `${this.type}`;switch(type) {case '3':type = '景區公告';break;case '6':type = '餐飲住宿';break;case '7':type = '周邊景點';break;case '13':type = '預訂門票';break;case '14':type = '特色購物';break;case '15':type = '景區服務';break;}return type;},},components: {vHeader, listTpl, loading, vFooter},created() {this.type = this.$route.params.type;},mounted() {// 頁面初始化時加載數據this.initPage();},// 只在當前路由改變,但是該組件被復用時調用// to 表示 route即將要進去的路由// from 表示 route正要離開的路由beforeRouteUpdate(to, from, next) {this.type = to.params.type;next(this.initPage()); },methods: {initPage() {// 判斷footer底部導航欄的顯示位置if(this.type == 6) {this.index = 2; } else if (this.type == 15) {this.index = 0;}this.$data.serviceInfo = []; // 初始化數據,防止footer底部導航欄切換數據沒有清空this.done = true;let url = `/JSY_H5/h5/queryServiceList?type=${this.type}`;this.$http.get(url).then((response) => {// 遍歷數據,改變數據結構,套用同一天模板listTplresponse.data.rows.forEach((item, index) => {let tmp = {};tmp['description'] = item['INFO_DESCRIPTION'];tmp['id'] = item['INFO_NO'];tmp['imageUrl'] = item['INFO_IMAGE_URL'];tmp['title'] = item['INFO_TITLE'];tmp['qrCode'] = item['QR_CORE_URL'];tmp['jumpUrl'] = item['JUMP_URL'];this.$data.serviceInfo.push(tmp);});this.$data.done = false;}, (response) => {this.$data.done = false;});}}}</script> //src\page\travelBox.vue
<template><div><v-header goBack="true" headTitle="旅行百寶箱"></v-header><div class="travel-box"><section class="item-box"><router-link :to="{name: 'listDetail', params: {id: 5, type: 20, identifier: 0}}"><i class="iconfont"></i><span>旅游線路</span></router-link><router-link :to="{name: 'externalMap'}"><i class="iconfont"></i><span>外部交通</span></router-link><router-link :to="{name: 'listDetail', params: {id: 4, type: 21, identifier: 0}}"><i class="iconfont"></i><span>景區地圖</span></router-link><router-link :to="{name: 'service', params: {type: 7}}"><i class="iconfont"></i><span>周邊景點</span></router-link><router-link :to="{name: 'service', params: {type: 6}}"><i class="iconfont"></i><span>餐飲,住宿</span></router-link></section> </div></div>
</template><script>import vHeader from '../components/header'export default {data() {return {}},components: {vHeader},mounted() {}}</script><style scoped lang="scss">.travel-box {margin-top: 42px;height: 100vh;background: #F5F5F5;a {display: inline-block;width: 32%;height: 100px;margin: 0 2% 2% 0;color: #5D656B;background: #fff;text-align: center;box-sizing: border-box;&:nth-child(3n + 0) {margin-right: 0;}i {display: block;font-size: 48px;line-height: 60px;margin-top: 10px;}span {font-size: 16px;}}}@media screen and (min-width: 1000px) {.travel-box {margin-top: 100px;a {height: 200px;i {font-size: 64px;line-height: 100px;}span {font-size: 24px;}}}}
</style> //listDetail
<template><div class="detail"><v-header goBack="true" :headTitle="listDetail.title"></v-header><div class="audio-play" v-if="this.identifier == 1 && listDetail.audio"><i v-on:click="playAudio" class="iconfont"> 音頻播放</i><audio id="audio" :src="listDetail.audio" loop="true">你的瀏覽器不支持 <code>audio</code> 音頻播放功能.</audio></div><div class="detail-body" v-show="isShow"><section v-html="listDetail.content"></section><review :id="detailId" :qrCodeUrl="qrCodeUrl" v-if="needReview"></review></div><loading :show="done"></loading></div>
</template><script>import loading from '../components/loading.vue';import vHeader from '../components/header.vue';import review from '../components/review.vue';export default {data() {return {done: false,isShow: false, // 只有當數據加載完成之后才能夠實現出來needReview: false, //是否需要顯示評論(只有景點才需要,其他的地方都是不需要的,默認關閉)detailId: '',type: '', // 判斷當前的模塊信息identifier: '', // 標識符 景點介紹模塊為1 旅行百寶箱模塊為0shopUrl: '',qrCodeUrl: '', // 二維碼的生成地址listDetail: { // 詳情列表信息title: '',content: '',audio: null}}},components: {loading, vHeader, review},created() {this.detailId = this.$route.params.id;this.identifier = this.$route.params.identifier || 0;this.type = this.$route.params.type;},mounted() {this.initPage();},methods: {initPage() {let listDetailUrl = '';this.$data.done = true;if(this.identifier == 1) { listDetailUrl = `/JSY_H5/h5/querySSSOne?id=${this.detailId}`; // 景點介紹調用的接口} else if(this.identifier == 2) {listDetailUrl = `/JSY_H5/h5/queryServiceOne?id=${this.detailId}`; // service.vue下面過來調用接口} else {listDetailUrl = `/JSY_H5/h5/queryServiceList?type=${this.detailId}`; // 旅游線路,景區地圖調用的接口}this.$http.get(listDetailUrl).then((response) => {this.done = false;this.isShow = true;let data = response.data.rows;// 景點介紹if(this.identifier == 1) {this.listDetail.title = data[0].SS_TITLE;this.listDetail.content = data[0].SS_CONTENT;this.listDetail.audio = data[0].SS_VIDEO_URL;this.qrCodeUrl = data[0].QR_CORE_URL;this.needReview = true;} else {// 資訊this.listDetail.title = data[0].INFO_TITLE;this.listDetail.content = data[0].INFO_CONTENT;this.needReview = false;}// 由于后臺傳過來是一段字符串 需要使用正則來適配一體機文字大小let isApp = window.localStorage ? localStorage.getItem('isApp') : Cookie.read('isApp');if(isApp == 'true') {this.listDetail.content = this.listDetail.content.replace(/font-size:\s*\d+px;/g, 'font-size: 32px;');}}, (response) => {console.log('opps Is Error: ' + response);this.done = false;})},playAudio() {let audio = document.getElementById('audio');var isPlaying = audio.currentTime > 0 && !audio.paused && !audio.ended && audio.readyState > 2;if (!isPlaying) {audio.load(); audio.play();}}}}
</script><style lang="scss">.detail {padding-top: 40px; // 移除頭部header的高度.audio-play {width: 100%;color: #fff;padding: 1% 4%;text-align: right;background: #000;opacity: .4;box-sizing: border-box;i {display: inline-block;width: 100px;height: 30px;line-height: 30px;}}.detail-body {padding: 10px 10px 40px 10px ;section {width:100%;img {width:100%;}}}footer {position: absolute;right: 0;bottom: 0;width: 100%;height: 40px;background: #f6f6f6;text-align: right;a {display: inline-block;width: 80px;height: 40px;line-height: 40px;padding: 2px;color: #FFF;text-align: center;background: #e60012;box-sizing: border-box;}}}@media screen and (min-width: 1000px) {.detail {padding-top: 100px;.audio-play {i {font-size: 32px;width: 200px;height: 50px;line-height: 50px;}}footer {height: 100px;}}
}
</style> 這個組件中引用了review組件
<template><div><div class="reviews" v-show="isShow"><ul><li><i class="iconfont"></i>{{ visitCount }}</li><li @click.once="upVote" :class="{active: isActive }"><i class="iconfont"></i>{{ goodCount }}</li><li @click="showReviewBox"><i class="iconfont"></i>寫評論</li><li @click="showCommentBox"><i class="iconfont"></i>{{ reviewCount }}</li></ul></div><transition name="slide-fade-down"><div v-show="isShowReviewBox" class="reviews-box"><div class="header"><span @click="closeReviewBox">取消</span><span>評論</span><span @click="addReview" :class="isSend">發送</span></div><div class="body"><textarea v-model="reviewContent" autofocus maxlength="120" required></textarea></div></div></transition><transition name="slide-fade-right"><div v-show="isShowCommentBox" class="comment-box"><div @click.stop.prevent="closeCommentBox" class="mask"></div><div class="comment-main"><section v-for="(item, index) in reviewData"><div class="reviews-author"><span>游客</span></div><div class="reviews-body"><p class="reviews-content">{{ item.SSR_CONTENT }}</p><p>{{ item.ENTRY_DATE_TIME | time}}</p></div></section></div></div></transition><div v-if="isShowQrBox" id="qrcode" @click="closeQrcodeBox"><div class="mask"></div><div id="qrcode-content"></div></div><div v-if="isShowTipBox" class="tip-box">您的評論已經提交,請等待審核通過...</div></div>
</template><script>import Vue from 'vue';import '../static/lib/js/jquery.qrcode.min.js'export default {data() {return {isShow: true, SS_NO: this.id, // 當前的景點idisActive: false,reviewData: [], // 評論數visitCount: 0, // 訪問數goodCount: 0, // 點贊數reviewCount: 0, // 評論數reviewContent: '', // 評論內容isShowReviewBox: false, // 是否顯示評論框isShowCommentBox: false, // 是否顯示評論列表isShowQrBox: false, // 是否顯示二維碼isShowTipBox: false // 是否顯示評論成功提示框}},props: ['id', 'qrCodeUrl'],mounted() {this.initPage();},computed: {isSend: function () {return {active: !!this.$data.reviewContent.length} }},filters: {// 格式化時間time: function(date) {if(!date) return '';var date = new Date(date);var Y = date.getFullYear() + '-';var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' ';return Y + M + D;}},methods: {// 評分showRate(rate) {if(!rate) rate = 5;return "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);},// 判斷是否顯示評論界面showReviewBox() {let isApp = window.localStorage ? localStorage.getItem('isApp') : Cookie.read('isApp');if(isApp == 'true') { // 如果當前是一體機訪問 則無法添加評論 調出二維碼let url = this.qrCodeUrl;this.$data.isShowReviewBox = false;this.isShowQrBox = true;jQuery('#qrcode #qrcode-content').empty();Vue.nextTick(function() {jQuery('#qrcode #qrcode-content').qrcode(url); // 使用ES6來進行字符串轉義});} else {this.$data.isShowReviewBox = !this.$data.isShowReviewBox;}},showCommentBox() {if(this.reviewCount == 0) return false; // 如果當前的評論數為0 則不顯示評論列表this.$data.isShowCommentBox = !this.$data.isShowCommentBox;},// 關閉評論界面closeReviewBox() {this.$data.isShowReviewBox = false;},closeCommentBox() {this.$data.isShowCommentBox = false;},// 添加評論addReview() {let url = `/JSY_H5/h5/saveSSR`;this.$http.post(url, {SS_NO: this.$data.SS_NO,SSR_CONTENT: this.$data.reviewContent}).then( (response) => {this.closeReviewBox();this.reviewContent = '';this.isShowTipBox = true;// 需要使用箭頭函數來邦定this的值setTimeout(() => {this.isShowTipBox = false;}, 1000);}, (response) => {console.log('opps Is Error: ' + response);})},initPage() {let url = `/JSY_H5/h5/querySSRList?id=${this.$data.SS_NO}`;this.$http.get(url).then((response) => {this.$data.reviewData = response.data.rows;}, (response) => {console.log('opps Is Error: ' + response);});this.getUserVisit(); // 獲取評論接口中 訪問量和點贊數},// 獲取當前景點的頁面訪問量點贊數以及評論數getUserVisit() {let url = `/JSY_H5/h5/addInteractive?id=${this.$data.SS_NO}`; // 游客訪問量this.$http.get(url).then((response) => {this.$data.goodCount = response.data.GOODED_COUNT;this.$data.visitCount = response.data.LOOKED_COUNT;this.$data.isActive = response.data.IS_GOODED;this.$data.reviewCount = response.data.REVIEW_COUNT;}, (response) => {console.log('opps Is Error: ' + response);});},// 添加點贊upVote() {let url = `/JSY_H5/h5/addInteractive?id=${this.$data.SS_NO}&ACTION="good"`; // 當前景點-點贊數this.$http.get(url).then((response) => {this.$data.goodCount = response.data.GOODED_COUNT;this.$data.isActive = true;}, (response) => {console.log('opps Is Error: ' + response);});},// 關閉二維碼框closeQrcodeBox() {this.isShowQrBox = false;}}}
</script><style scoped lang="scss">/* 底部詳情操作框 */.reviews {position: fixed;bottom: 0;left: 0;right: 0;height: 60px;z-index: 100;background: #F6F6F6;ul {padding: 0 5%;li {display: inline-block;width: 25%;height: 30px;line-height: 30px;margin: 15px 4% 0 0;text-align: center;border-radius: 10%;background: #fff;box-sizing: border-box;i {margin-right: 5px;}&:last-child {color: #e60012;width: 13%;margin-right: 0;}}}/* 選中樣式 */.active {color: #e60012;pointer-events: none;}}/* 評論框基本樣式 */.reviews-box {position: fixed;left: 0;right: 0;bottom: 0;z-index: 200;width: 100%;height: 100px;padding: 2% 8% 5%; background: #F6F6F6;box-sizing: border-box;.header {width: 100%;padding-bottom: 5px;text-align: center;span {color: #000;&:first-child {float: left;}&:last-child {float: right;color: #333;pointer-events: none;&.active {pointer-events: auto;color: #e60012;}}}}/* 用戶編輯框 */.body {textarea {min-height: 40px;width: 100%;padding: 2%;font-size: 14px;border-radius: 5%;border: 2px solid #F6F6F6;background: #fff;box-sizing: border-box;resize: none;box-shadow: none;}}}/* 動畫效果 */.slide-fade-down-enter-active, .slide-fade-down-leave-active {transition: all 1s ease-in;}.slide-fade-down-enter, .slide-fade-down-leave-to{transform: translate3d(0, 100px, 0);}.slide-fade-right-enter-active, .slide-fade-right-leave-active {transition: all 1s ease-in;}.slide-fade-right-enter, .slide-fade-right-leave-to{transform: translate3d(100%, 0, 0);}.tip-box {position: absolute;left: 50%;top: 50%;transform: translate3d(-50%, -50%, 0);width: 200px;height: 100px;font-size: 18px;text-align: justify;padding: 10px 20px;background: #fff;box-shadow: 1px 1px 10px rgba(0, 0, 0, .5);box-sizing: border-box;}/* 右側評論列表 */.comment-box {position: fixed;top: 40px;bottom: 50px;right: 0;width: 80%;overflow-y: auto;background: #F6F6F6;.mask {position: fixed;display: block;left: 0;right: 0;top: 0;bottom: 0;background: rgba(0, 0, 0, .5);z-index: 100;}.comment-main {position: relative;z-index: 100;section {min-height: 80px;padding: 2%;background: #fff;overflow: hidden;text-align: left;font-size: 14px;border-bottom: 2px solid #F6F6F6;box-sizing: border-box;.reviews-author {float: left;width: 25%;height: 80px;padding-left: 4%;margin-right: 2%;color: #333;box-sizing: border-box;}.reviews-body {min-height: 80px;overflow: hidden;.reviews-content {min-height: 40px;}p {&:first-child span {color: #e60012;}&:last-child {font-size: 12px;}}}}}}@media screen and (min-width: 1000px) {.comment-box {top: 100px;bottom: 60px;.comment-main {section {font-size: 32px;.reviews-body {p {&:last-child {font-size: 24px;}}}}}}}#qrcode {position: relative;.mask {position: fixed;display: block;left: 0;right: 0;top: 0;bottom: 0;background: rgba(0, 0, 0, 0.4);z-index: 10;}#qrcode-content {position: fixed;left: 50%;top: 50%;padding: 15px;text-align: center;background: #fff;z-index: 100;transform: translate3d(-50%, -50%, 0);&:after {content: '掃一掃上面的二維碼圖案';display: block;padding-top: 10px;}}}
</style> //src\page\externalMap.vue
<template><div><v-header goBack="true" headTitle="外部地圖"></v-header><div class="travel-box"><div id="allmap"></div></div></div>
</template><script>import vHeader from '../components/header'export default {data() {return {}},components: {vHeader},mounted() {//百度地圖API功能var map = new BMap.Map("allmap"); // 創建Map實例map.centerAndZoom(new BMap.Point(119.199201,34.019519), 18); // 初始化地圖,設置中心點坐標和地圖級別map.addControl(new BMap.MapTypeControl()); //添加地圖類型控件map.setCurrentCity("淮安國緣賓館"); // 設置地圖顯示的城市 此項是必須設置的map.enableScrollWheelZoom(true); //開啟鼠標滾輪縮放// 編寫自定義函數,創建標注function addMarker(point){var marker = new BMap.Marker(point);map.addOverlay(marker);}// 向指定地圖里面添加標注addMarker(new BMap.Point(119.199201,34.019519));}}
</script><style scoped lang="scss">.travel-box {margin-top: 60px;}#allmap {width: 100%;height: 400px;}@media screen and (min-width: 1000px) {.travel-box {margin-top: 100px;}#allmap {height: 600px;}}
</style> 后記:我挺喜歡這個項目的代碼的,哈哈哈,因為都看得懂,還能夠猜到作者的意圖。
轉載于:https://www.cnblogs.com/smart-girl/p/11166096.html
總結
以上是生活随笔為你收集整理的【vue】vue-znly的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript Collectio
- 下一篇: 网络2网络布线与数制转换