前言
有好几天没更新文章了. 这段实际忙着做了一个 vue 的项目, 从 19 天前开始, 到今天刚好 20 天, 独立完成.
做 vue 项目做这个项目一方面能为工作做一些准备, 一方面也精进一下技术.
技术栈: vue2 + vuex + vue-router + webpack + ES6/7 + element-ui + vue-baidu-map + I18N + vue-awesome-swiper
做项目时总是有一些思考和踩过的坑, 对以后有一定的帮助, 今天就来写写做 vue 项目遇到的那些事.
假如你正准备做项目或正在做项目一定看看, 说不定对你有所帮助.
正文
照例放上一些项目中用到的权威的官网
vue 官方 API:https://cn.vuejs.org/
vue 资源精选: http://vue.awesometiny.com/
vue GitHub 地址: https://github.com/vuejs/vue
element-ui 官方中文 API:http://element-cn.eleme.io/#/zh-CN/component/dropdown
vue-awesome-swiper GitHub 地址: https://surmon-china.github.io/vue-awesome-swiper/
1. 阅读 vue 的风格指南 https://cn.vuejs.org/v2/style-guide/ 再开始你的项目 (最重要)
2.vue 项目中 data 可以视为一个函数
- <script>
- export default {
- data () {
- // 可以在这里写很多的前置数据操作
- return {}
- }
- }
- </script>
例如:
- <script>
- export default {
- data () {
- // 可以在这里写很多的前置数据操作
- // 不在首页时隐藏切换语言
- let showLanguageList
- if (
- this.$route.path === '/Home' ||
- this.$route.path === '/' ||
- ) {
- showLanguageList = true
- } else {
- showLanguageList = false
- }
- return {
- showLanguageList: showLanguageList
- }
- }
- }
- </script>
3. 路由带参
路由带参: 点击查看官网说明
我们可以在路由切换时绑定参数
在 App.vue 文件中监听路由绑定参数
- watch: {
- $route (to, from) {
- // 在路由上绑定语言和公司编号
- this.$router.replace({
- path: this.$router.path,
- query: {
- languageCode: '中文',
- companyCode: '阿里巴巴'
- }
- })
- }
- }
函数 query 传参可以和路由绑定 id 一起使用
路由绑定 ID:
- const User = {
- template: '<div>User {{ $route.params.id }}</div>'
- }
- const router = new VueRouter({
- routes: [
- { path: '/user/:id', component: User }
- ]
- })
效果:
4. 解决整个项目的数据刷新问题
需求: 在项目中经常会用到点击某个按钮或者更新某个参数时, 整个项目的后台数据都从新请求一遍或者刷新整个页面.
类似 F5 刷新
- this.$router.go(0);
- location.reload()
- // 这两种方式都相当于 f5 刷新, 页面会有卡顿, 白屏的情况, 用户体验极差
通过 v-if 的显示, 消失, 刷新数据
适用于整个项目的数据刷新, 当然也可以用于刷新部分页面
页面刷新相对流畅, 比较推荐的一种方法
在 App.vue 中:
- <template>
- <div id="app">
- <router-view v-if="isRouterAlive" />
- </div>
- </template>
- <script>
- export default {
- name: 'App',
- provide () {
- return {
- reload: this.reload
- }
- },
- data () {
- return {
- isRouterAlive: true
- }
- },
- methods: {
- reload () {
- this.isRouterAlive = false
- this.$nextTick(function () {
- this.isRouterAlive = true
- })
- }
- }
- }
- </script>
- <style>
- </style>
在子组件中, 当我们需要刷新数据时:
- <template>
- <div @click="onSubmit_name"></div>
- </template>
- <script>
- export default {
- data () {
- return {}
- },
- inject: ['reload'], // 引入方法
- methods: {
- onSubmit_name() {this.reload()} // 需要刷新数据的时候调用 reload 方法
- }
- </script>
- <style>
- </style>
利用路由的 replace 方法
这种方式是进入一个空白页, 在空白页里面跳转回原来的页面, 这种方式页面刷新相对流畅
- // 需要刷新数据的页面,
- refresh () {
- this.$router.replace({
- path: '/refresh',
- query: {
- t: Date.now() // 携带必要的路由参数
- }
- })
- }
- // refresh.vue 页面中里有路由钩子, 直接返回前一个页面
- <script>
- export default {
- beforeRouteEnter(to, from, next) {
- next(vm => {
- vm.$router.replace(from.path)
- })
- }
- }
- </script>
5.element-ui 导航栏与路由
激活导航跳转对应路由
在 element-ui 的导航中, 官方让我们能和 vue 的 router 无缝对接, 实现绑定路由, 同样可以根据路由实现对应导航栏高亮.
router 是否使用 vue-router 的模式, 启用该模式会在激活导航时以 index 作为 path 进行路由跳转 boolean - false
请看图中标红的位置, 添加 router 以后, 每次激活导航时以 index 作为 path 进行路由跳转
- <el-menu router :default-active="activeIndex" class="el-menu-vertical-demo hidden-sm-and-up" mode="vertical" :collapse="isCollapse" style="height:62px;float:right;width:100%;border:0;z-index:100"
- background-color="#222" text-color="#fff" active-text-color="#e42828">
- <el-submenu index="1">
- <template slot="title">
- <i class="el-icon-menu"></i>
- <span slot="title">{{$t('home.home')}}</span>
- </template>
- <el-menu-item-group>
- <el-menu-item index="/Pages">{{$t('home.home')}}</el-menu-item>
- <el-menu-item index="/PagesAbout">{{$t('home.about')}}</el-menu-item>
- <el-menu-item index="/PagesProductList">{{$t('home.product')}}</el-menu-item>
- <el-menu-item index="/PagesService">{{$t('home.service')}}</el-menu-item>
- <el-menu-item index="/PagesNewsList">{{$t('home.news')}}</el-menu-item>
- <el-menu-item index="/PagesRecruitmentList">{{$t('home.recruitment')}}</el-menu-item>
- <el-menu-item index="/PagesContact">{{$t('home.contact')}}</el-menu-item>
- <el-menu-item index="/PagesDownload">{{$t('home.download')}}</el-menu-item>
- </el-menu-item-group>
- </el-submenu>
- </el-menu>
根据对应路由实现对应导航高亮
请看如下代码, 重点关注红色部分
- <el-menu router :default-active="activeIndex" class="el-menu-demo hidden-xs-only" mode="horizontal" style="height:62px;float:right;width:100%;border:0;z-index:100"
- background-color="#222" text-color="#fff" active-text-color="#e42828">
- <el-menu-item index="/Pages">{{$t('home.home')}}</el-menu-item>
- <el-menu-item index="/PagesAbout">{{$t('home.about')}}</el-menu-item>
- <el-menu-item index="/PagesProductList">{{$t('home.product')}}</el-menu-item>
- <el-menu-item index="/PagesService">{{$t('home.service')}}</el-menu-item>
- <el-menu-item index="/PagesNewsList">{{$t('home.news')}}</el-menu-item>
- <el-menu-item index="/PagesRecruitmentList">{{$t('home.recruitment')}}</el-menu-item>
- <el-menu-item index="/PagesContact">{{$t('home.contact')}}</el-menu-item>
- <el-menu-item index="/PagesDownload">{{$t('home.download')}}</el-menu-item>
- </el-menu>
我们可以利用 vue 的特性, 动态的改变 default-active 的值来改变导航栏的高亮, 当然我们也可以通过截取的方式,
只要路由中有一部分路由和 index 相同则激活.
default-active 当前激活菜单的 index string
代码如下:
- URL:http://localhost:8080/#/PagesNewsList/4dd8136dec5c48bcb223e9ef1fa5714f?languageCode=zh-CN&companyCode=0000 let pathss = this.$route.path.split('/')
- let pathss = this.$route.path.split('/') // 截取路由
- data () {
- return {
- activeIndex: '/' + pathss[1] // 将路由中红色的地方设置为对应导航高亮. 不可忘记'/', 注意下标越界.
- }
- }
6. 如何实现单页面的 title 设置?
网上也有很多方法, 但我这里强烈推荐一个插件, 方便又实用.
vue-wechat-title
下载安装插件依赖
NPM install vue-wechat-title --save
在 main.JS 中引入插件
- import VueWechatTitle from 'vue-wechat-title'
- Vue.use(VueWechatTitle)
路由定义 (只截取一部分)
- // ...
- const routes = [
- {
- name: 'Home',
- path: '/home',
- meta: {
- title: '首页'
- },
- component: require('../views/Home.vue')
- },
- {
- name: 'Order',
- path: '/order',
- meta: {
- title: '订单'
- },
- component: require('../views/Order.vue')
- },
- {
- name: 'UCenter',
- path: '/ucenter',
- meta: {
- title: '用户中心'
- },
- component: require('../views/UCenter.vue')
- }
- ]
- // ...
App.vue 建议全局只使用一次该指令 标题可用 vuex 或者 router 中定义 不要多处使用!!
- <!-- 任意元素中加 v-wechat-title 指令 建议将标题放在 route 对应 meta 对象的定义中 -->
- <div v-wechat-title="$route.meta.title">
- </div>
- <!--or-->
- <router-view v-if="isRouterAlive" v-wechat-title='$route.meta.title' />
7. 路由加载方式
路由都有两种加载方式.
一种是懒加载
只在你点击或者访问的时候加载. 建议用于不经常访问的路由.
路由配置如下:
- {
- path: '/Home',
- name: 'Home',
- component: () => import('./views/Home.vue'),
- meta: {
- title: '首页'
- }
- }
一种是普通加载
在项目启动时就渲染好静态页面, 建议用于经常访问的路由, 增加效率以及提升体验.
- import PagesHome from './pages/home/Home.vue'
- {
- path: '/Pages',
- name: '/Pages',
- component: PagesHome,
- meta: {
- title: '首页'
- }
- }
8. 默认路由以及 404 页面
直接在 router.JS 页面中填入下面代码
- export default new Router({
- routes: [
- {
- path: '/', // 项目启动页
- redirect:'/Home' // 重定向到下方声明的路由
- },
- {
- path: '*', // 404 页面
- component: () => import('./notFind') // 或者使用 component 也可以的
- },
- ]
- })
9. 数据持久化
做 vue 项目时, 为了防止 f5 以后数据重置, 我们想到了数据持久化
巧用 vue-cookie 插件
传送门: https://www.npmjs.com/package/vue-cookie
NPM 方式安装
NPM install vue-cookie --save
在 main.JS/App.JS 中引用
- // Require dependencies
- var Vue = require('vue');
- var VueCookie = require('vue-cookie');
- // Tell Vue to use the plugin
- Vue.use(VueCookie);
示例:
- // From some method in one of your Vue components
- this.$cookie.set('test', 'Hello world!', 1);
- // This will set a cookie with the name 'test' and the value 'Hello world!' that expires in one day
- // To get the value of a cookie use
- this.$cookie.get('test');
- // To delete a cookie use
- this.$cookie.delete('test');
高级示例:
- // Setting the cookie Domain
- this.$cookie.set('test', 'Random value', {
- expires: 1, domain: 'localhost'
- });
- // As this cookie is set with a domain then if you wish to delete it you have to provide the domain when calling delete
- this.$cookie.delete('test', {
- domain: 'localhost'
- });
- // Customizing expires
- var date = new Date;
- date.setDate(date.getDate() + 21);
- this.$cookie.set('dateObject', 'A date object', {
- expires: date
- });
- this.$cookie.set('dateString', 'A parsable date string', {
- expires: date.toGMTString()
- });
- this.$cookie.set('integer', 'Seven days later', {
- expires: 7
- });
- this.$cookie.set('stringSuffixY', 'One year later', {
- expires: '1Y'
- });
- this.$cookie.set('stringSuffixM', 'One month later', {
- expires: '1M'
- });
- this.$cookie.set('stringSuffixD', 'One day later', {
- expires: '1D'
- });
- this.$cookie.set('stringSuffixh', 'One hour later', {
- expires: '1h'
- });
- this.$cookie.set('stringSuffixm', 'Ten minutes later', {
- expires: '10m'
- });
- this.$cookie.set('stringSuffixs', 'Thirty seconds later', {
- expires: '30s'
- });
- (我们也可以在 vuex 的 store 中使用)
巧用 vuex-persistedstate 插件
前提: 已经安装并使用 vuex.
安装 vuex-persistedstate
NPM install vuex-persistedstate
在 vuex 的 store 文件的 index.JS 中引用
- import Vue from 'vue'
- import Vuex from 'vuex'
- import createPersistedState from 'vuex-persistedstate'
- import state from './state'
- import mutations from './mutations'
- Vue.use(Vuex)
- export default new Vuex.Store({
- state,
- mutations,
- plugins: [createPersistedState()]
- })
10.vue 官网的推荐资源中, 基本能找到我们想要的资源
1. 推荐一个地图插件: https://github.com/Dafrok/vue-baidu-map (百度地图) https://github.com/xkjyeah/vue-google-maps (谷歌地图)
文档: https://dafrok.github.io/vue-baidu-map/
安装
NPM i --save vue-baidu-map
在 main.JS 中引入
- // 引入百度地图插件
- import BaiduMap from 'vue-baidu-map'
- Vue.use(BaiduMap, {
- // ak 是在百度地图开发者平台申请的密钥 详见 http://lbsyun.baidu.com/apiconsole/key */
- ak: 'Zgbme5XaLreej7Oribs9yk317sOFG3OP'
- })
使用示例:
- <baidu-map class="map" :center="center" :zoom="zoom" @ready="handler">
- <bm-geolocation anchor="BMAP_ANCHOR_BOTTOM_RIGHT" :showAddressBar="true" :autoLocation="true"></bm-geolocation>
- <bm-marker :position="{lng: this.$store.state.companyObject.longitude, lat: this.$store.state.companyObject.latitude}" :dragging="false"animation="BMAP_ANIMATION_BOUNCE">
- <bm-label :content="this.$store.state.companyObject.transname" :labelStyle="{color:'red', fontSize :'14px'}" :offset="{width: -35, height: 25}" />
- </bm-marker>
- <bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
- <bm-map-type :map-types="['BMAP_NORMAL_MAP','BMAP_HYBRID_MAP']" anchor="BMAP_ANCHOR_TOP_LEFT"></bm-map-type>
- </baidu-map>
- export default {
- name: 'Contact',
- components: {
- ContactUs
- },
- data () {
- return {
- center: {
- lng: '26.515515',
- lat:'103.54548841'
- },
- zoom: 15
- }
- },
- methods: {
- handler ({ BMap, map }) {
- this.center.lng ='26.515515'
- this.center.lat = '103.54548841'
- this.zoom = 15 } } }
2. 推荐一个 vue 轮播插件: https://github.com/surmon-china/vue-awesome-swiper
安装
NPM install vue-awesome-swiper --save
引用:
- import Vue from 'vue'
- import VueAwesomeSwiper from 'vue-awesome-swiper'
- // require styles
- import 'swiper/dist/css/swiper.css'
- Vue.use(VueAwesomeSwiper, /* {
- default global options
- } */)
示例:(每个都是 vue 项目的示例, 在右上角都有对应代码的链接)
https://surmon-china.github.io/vue-awesome-swiper/
3. 推荐一个 vue 国际化插件: https://github.com/kazupon/vue-i18n
文档: http://kazupon.github.io/vue-i18n/
使用方法请参考文档, 非常详尽. element-ui 已经兼容 vue-I18N@5.x
结尾
vue 现在已经相当成熟, 能做的事情还有很多, 大家在使用过程中如果有什么问题, 欢迎交流, 一起学习, 一起进步.
年前就写好了. 想着过年大家都没心思看, 就拖到现在.
代码是敲不玩的, 这辈子都不可能敲完了, 只能不断学习. 哈哈
来源: https://www.cnblogs.com/clwydjgs/p/10291136.html