天天看点

004--自找麻烦之 vue2.0人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!

人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!

1. Vuex:用于各个组件的数据共享

2. Nuxt.js : 基于vue的服务端渲染应用框架

3. 任何一门框架的学习最好的资料就是官方文档     

4. vue 不支持IE8以下的浏览器(记住)

5. 要在外面取vue实例app里面的data要用: app.$data

6. 学习vue只需要操作数据,不会再涉及到DOM的操作

7. vue的双向数据绑定原理(面试会问,重要,以后补充)

8. vue注册全局组件用 component ;子组件接收父组件的数据要用 props           

Vue.component("TodoItem",{
   props:['content'],
   template:"<li>{{content}}</li>"
})
           
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
           

9. 子组件传递数据给父组件

10. 生命周期函数就是vue实例在某一个时间点会自动执行的函数

        beforeCreate(vue实例进行部分初始化之后会执行);created(完全初始化之后执行);

        beforeMount(模板结合vue实例的DOM元素挂载到页面之前执行),mounted(页面挂载之后 执行);

        beforeDestroy(组件被销毁之前执行,在控制台调用 vm.$destroy() 时这个函数就执行),destroyed(组件被完全销毁之后执行);

        beforeUpdate(当数据发生还没重新渲染之前执行),updated(当数据发生改变重新渲染之后执行)

11. vue指令里面的值不再是字符串,而是js表达式

12. v-text 和 v-html有点类似,区别在于v-text="name"(和 {{name}} 的用法一模一样)做了转义,完整输出内容,而v-html 可以识别html表达式

13. 计算属性 computed(非常重要的特点:内置缓存)的写法(写成函数,返回这个值)   

new Vue({
  ...
  computed:{
    fullName:function(){
      return this.fname + this.lname
    }
  }
})
           
<div id="app">{{fullName}}</div>
           

14. computed 的 get (获取值时执行)和 set(设置值时执行)

new Vue({
  ...
  computed:{
    fullName:{
       get:function(){
         return this.fname + this.lname
       },
       set:function(value){
         var arr = value.split(" ");
         this.fname = arr[0];
         this.lname = arr[1];
       }
    }
  }
})
           

15. div绑定某个类名用 :class="{activated: isActivated}" 取决于isActivated是true还是false

     :class="[activated]" 这样写activated代表一个变量,变量的内容即是一个类名

16. Vue.set()不光能修改数据,还能添加数据,弥补了Vue数组变异方法的不足; Vue.set()在methods中也可以写成this.$set()

17. vue-cli 的使用

        npm i -g vue-cli

        vue init webpack Travel      (Travel 表示项目放在哪个文件夹下)

        基本回车操作,除了一些没见过的选项你不想安装就选择no   

        cd Travel

        npm run dev     

18. vue-cli 生成的项目文件分析

           package-lock.json  package的锁文件(帮助我们确定你安装的第三方包的版本,保持团队编程的统一)

           .eslintrc.js   配置了一些代码的规范

           .eslintignore     忽略某些文件的检测

           .editorconfig     配置了编辑器的语法       

           static目录       图片,json数据等静态资源

           src目录     整个项目的源代码

           config目录     项目的配置文件

    vue-cli生成的项目中, @ 符号代表 src 目录(这是在build目录中webpack.base.conf.js中帮我们设置好的)

19. 路由就是根据网址的不同,返回不同的内容给用户

20.  <router-view></router-view>   显示当前路由地址所对应的内容

21. 单页应用通过js感知url的变化,动态删除再渲染新的DOM结构,把组件内容挂载到页面上,这时候路由是由前端来做的。

22. 单页应用首屏时间慢且SEO差(搜索引擎只认识HTMl当中的内容),多页应用首屏时间快且SEO好

23. 做移动端的页面可以写以下的语句防止用户用手缩放网页

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
           

24. reset.css 文件:对基础样式的修饰,保证所有浏览器显示的效果基本一致

     border.css文件: 为了解决多倍屏1像素边框会被显示成多元素的问题 (1像素边框的解决方案)

     npm i fastclick -S  :   fastclick用来解决移动端click时间300毫秒点击延迟的问题

25. iconfont 阿里巴巴矢量图标库: http://www.iconfont.cn/   (进入图标管理--我的项目--新建项目图标库)

26. 使用stylus:  npm i stylus -s  ;   npm i stylus-loader -s

27. 只对当前组件的样式有效 scoped

<style scoped>  
</style>
           

28. iconfont的使用:选择需要图标加入购物车,添加至项目,下载到本地,再把iconfont.css 和四个字体文件(.eot,.svg,.ttf,.woff)提取出来,将iconfont.css文件中引用字体文件的路径改好就可以用了,

// icon图标库使用 在main.js 中引入 iconfont.css

import 'styles/iconfont.css'

@font-face {font-family: "iconfont"; //这个是iconfont.css文件,修改这里的路径

src: url('./iconfont/iconfont.eot?t=1527149033233');

src: url('./iconfont/iconfont.eot?t=1527149033233#iefix') format('embedded-opentype'),

url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),

url('./iconfont/iconfont.ttf?t=1527149033233') format('truetype'),

url('./iconfont/iconfont.svg?t=1527149033233#iconfont') format('svg');

}

例如:

<span class="iconfont">&#xe624;</span>
           

    &#xe624;  是一种图标的16进制的字符标识 (可在iconfont的官网查看)

// icon图标库使用 main文件里面要引用

import 'styles/iconfont.css'

29. 在项目的build文件夹中的webpack.base.conf.js中为某些常见的路径配置变量别名,例如'styles':..

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'styles': resolve('src/assets/styles'),
    }
  }
           

    修改后要重启服务器才不会报错

30. 使用vue-awesome-swiper 来快速构建一个轮播 (新版本有点细节bug,采用老的版本 2.6.7)  

        github网址:https://github.com/surmon-china/vue-awesome-swiper

        npm i [email protected] -s   

<template>
    <div class="wrapper">
        <swiper :options="swiperOption" v-if="showSwiper">
            <swiper-slide v-for="item of list" :key="item.id">
                <img class="swiper-img" :src="item.imgUrl" />
            </swiper-slide>
            <div class="swiper-pagination" slot="pagination"></div>
        </swiper>
    </div>
</template>
           
data () {
        return{
            swiperOption: {
                pagination: '.swiper-pagination',
                loop: true,
                autoplay:fasle
            }
        }
    },
           

:options="swiperOption"  是 这个vue-awesome-swiper 的配置项,pagination是显示圆点,loop是循环播,autoplay是自动轮播

31. 当你要在子组件里面定义一个data的时候,data一定要是一个函数      

32. 最好的防止网速太慢轮播图图片没加载完下面的元素抖动的方案 (用vw的话兼容性差)     

.wrapper
   width: 100%
   height: 0
   overflow: hidden
   padding-bottom: 31.25%
   background-color: #eee
           

33. style用了scoped后样式只对本组件生效,但是有时候又想让某些样式应用于其他组件,所以可以用 >>>

<style  scoped>
    .wrapper >>> .swiper-pagination-bullet-active
        background: #fff
</style>
           

34. 谷歌浏览器下载一个插件 Vue.js devtools 

35. 对超过div宽度的文字显示成 ... 的CSS写法

overflow: hidden
white-space: nowrap
text-overflow: ellipsis      //ellipsis显示省略符号来代表被修剪的文本                显示省略符号来代表被修剪的文本      

36. 提到插槽的概念,不懂,后补

37. 数据请求推荐 axios

        npm i axios -s

import axios from 'axios' //在需要请求的.vue文件内

axios.get('/api/index.json')
        .then(this.getHomeInfoSucc)
           
methods: {
        getDetailinfo () {
            axios.get('/api/detail.json?',{
                params: {
                    id: this.$route.params.id      // this.$route.params 可以取到当前路由上定义的id参数的值,发get请求带参数就可以这样
                }
            }).then(this.handleGetDataSucc)
        },
           

38. vue-cli 生成的整个项目只有static目录里面的内容可以被外部访问到

39. vue-cli 生成的项目目录中 配置config文件夹下的index.js文件中的 module.exports    

dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api':{
        target: 'http://localhost:8080',
        pathRewrite: {
          '^/api':'/static/mock/'
        }
      }
    },
           

看 proxyTable 配置项,按如上配置 开发环境下的时候请求路径即使写的是 './api' ,它也会帮我们代理到 '/staic/mock'

这个功能是 webpack-dev-server 这个工具提供的

40. 父组件给子组件传值

<home-header :city="city"></home-header>
           
<script>
export default {
  name: 'HomeHeader',
  props: {
    city: String
  }
}
</script>
           
<div class="header-right">
   {{this.city}}
   <span class="iconfont arrow-icon"></span>
</div>
           

41. 页面跳转用   <router-link to='/city'></router-link>

42. 原生app的上下拉动页面效果的插件(到顶部和底部还有弹性的效果) better-scroll 的使用: 

        https://github.com/ustbhuangyi/better-scroll

        npm i better-scroll -s   

<div ref="wrapper">     //要类似这种DOM结构,父div里面一个子div,子div里面再写页面的东西
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- you can put some other DOMs here, it won't affect the scrolling -->
</div>
           
import Bscroll from 'better-scroll'  
export default {
    name: 'CityList',
    mounted () {
        this.scroll = new Bscroll(this.$refs.wrapper)    //把DOM元素丢进去实例化
    }
}
</script>
           
this.scroll.scrollToElement(element)    //这个方法是用来将页面滚动到某个DOM元素的区域的
           

43. vue2 用 ref 来获取 DOM        

<div class="touchscroll" ref='wrapper'></div>
           
this.$refs.wrapper
           

44. 兄弟组件之间的传值(兄传值给父,父再传给弟)

methods: {       //兄
        handleLetterClick (e) {
            this.$emit('change',e.target.innerText)
        }
    }
           
<city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list>       //父
<city-alphabet :cities="cities" @change="handleLetterChange"></city-alphabet>
           
handleLetterChange (letter) {    //父
            this.letter = letter
        }
           
props: {        //弟
        hot: Array,
        cities: Object,
        letter: String
    },
           
watch: {   //弟    注意这一步要在watch里面处理这个传过来的数据
        letter () {
            if (this.letter) {
                const element = this.$refs[this.letter][0]
                this.scroll.scrollToElement(element)
            }  
        }
    }
           

45. vue中html元素中不要有逻辑的部分,例如

<li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li>    //v-show 这里要改在computed 里面
           
computed: {             //改成这样
        hasNoData() {
            return !this.list.length
        }
}
           
<li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li>    // 改成这样
           

46. Vuex 数据层框架的使用: 就是类似一个仓库,组件共用的数据存放在State里面,外面的组件要改变这个共用数据要通过dispatch方法来调用actions的异步代码调用commit方法来调用Mutations(转变)的同步代码最终mutate(变化)到state里面的数据,外面的组件也可以直接通过Mutations来改变state里面的数据

        整个流程: 组件调用action,action调用mutations,Mutations去改变我们的数据

        npm i vuex -s

        vue-cli生成的项目中在src目录新建一个store文件夹/index.js文件

import Vue from 'vue'     // index文件内容
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        city: '北京'
    }
})
           
import store from './store'    //mian文件内容
...
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
           
<div class="header-right">
        {{this.$store.state.city}}        // 任何组件使用这个store上的共用数据的方法
        <span class="iconfont arrow-icon"></span>
      </div>
           

        以下是改变共享数据的过程;

methods: {     //组件执行这个函数 dispatch方法去调用actions
        handerCityClick (city) {
            this.$store.dispatch('changeCity',city)
        }
    },
           
import Vue from 'vue'       //这是store/index文件  actions触发Mutations最终改变state里面的city数据
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        city: '北京'
    },
    actions: {
        changeCity (ctx, city) {
            // console.log(city)
            ctx.commit('changeCity',city)
        }
    },
    mutations: {
        changeCity (state, city) {
            state.city = city
        }
    }
})
           

47. 编程式导航(路由通过js代码来实现页面路由的跳转了)

methods: {
        handerCityClick (city) {
            this.$store.commit('changeCity',city)
            this.$router.push('/')      // 这样就跳转到首页了
        }
    },
           

48. localstorage的用法

export default new Vuex.Store({
    state: {
        city: localStorage.city || '北京'
    },
    mutations: {
        changeCity (state, city) {
            state.city = city
            localStorage.city = city
        }
    }
})
           

更健壮的兼容浏览器的写法(加入try catch 处理某些浏览器关闭本地存储功能代码会报错的问题)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

let defaultCity = '汕头'
try {
    if (localStorage.city) {
        defaultCity = localStorage.city
    }
} catch (e) {}

export default new Vuex.Store({
    state: {
        city: defaultCity
    },
    mutations: {
        changeCity (state, city) {
            state.city = city
            try {
                localStorage.city = city
            }catch (e) {}

        }
    }
})
           

        谷歌浏览器,右键检查--选择 Application  可以找到 local storage 

49. 高级Vuex的api用法

import { mapState } from 'vuex'
export default {
  name: 'HomeHeader',
  computed: {
    ...mapState(['city'])   // 将state中共享数据映射到本组件的city数据身上
  }
}
           
<div class="header-right">
     {{this.city}}     //虽然这个city是共享数据,但是映射本组件就可以直接这样用了
</div>
           

50. 性能优化

<template>     // 这个是App.vue 文件
  <div id="app">
    <keep-alive exclude="Detail">      //用这个标签在前进后退页面的时候就不会重复发送ajax请求,会缓存第一次发送的ajax请求
      <router-view/>                   // exclude="Detail"  表示除了Detail组件不会缓存,其他都会缓存
    </keep-alive> 
  </div>
</template>
           
activated () {     // 重新显示页面比如说城市变了就要重新发送ajax请求就可以写在这个生命周期函数 activated 里面
    if (this.lastCity !== this.city) {
      this.lastCity = this.city
      this.getHomeInfo()
    }
  }
           

51. vue中的 <router-link></router-link> 类似 a 标签,但想表示其他标签也可以

<router-link tag='div' to="/" class="header-abs">       // 加上 tag="div" 就可以表示 div 了,同样加上其他就可以表示其他标签
     <div class="iconfont header-abs-back"></div>
</router-link>
           

52. 获取当前页面滚动条的纵坐标位置: 

document.documentElement.scrollTop;
           

53. 对全局事件的解绑

    activated () {    // 页面展示时执行
        window.addEventListener('scroll',this.handleScroll)
    },
    deactivated () {   // 页面切换掉后执行
        window.removeEventListener('scroll',this.handleScroll)
    }
           

54. 递归组件的实现(vue中比较难的部分)(组件自己调用自己)

<template>
    <div>
        <div class="item" v-for="(item,index) of list" :key="index">
            <div class="item-title border-bottom">
                <span class="item-title-icon"></span>
                {{item.title}}
            </div>
            <div v-if="item.children" class="item-children">    // v-if  与 加上自己子项的类名区分
                <detail-list :list="item.children"></detail-list>   //用自己的组件名
            </div>
        </div>
    </div>
</template>
<script>
export default {
    name: 'DetailList',   //组件名
    props: {
        list: Array
    }
}
           

55. ajax请求要放在 mounted 这个钩子函数里面中请求

56. 解决切换页面时页面滚动到上一个页面的位置的问题(查看官网 -- 滚动行为)

import Vue from 'vue'        // 这是router文件夹里面的 index.js 文件
import Router from 'vue-router'
import Home from '@/pages/home/Home'
import City from '@/pages/city/City'
import Detail from '@/pages/detail/Detail'

Vue.use(Router)

export default new Router({
  routes: [{
    path: '/',
    name: 'Home',
    component: Home
  },{
    path: '/city',
    name: 'City',
    component: City
  },
  {
    path: '/detail/:id',
    name: 'Detail',
    component: Detail
  }],
  scrollBehavior (to, from, savedPosition) {    //加上这段代码就可以解决
    return { x: 0, y: 0}
  }
})
           

57. 修改vue-cli生成的项目的package.json的启动配置项

"scripts": {
    "dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
  },
           

这样写就能通过ip地址访问webpack-dev启动的服务

58. vue项目的打包上线(针对vue-cli生成的项目)

        npm run build  打包编译

        把生成的dist目录中的东西给后端,扔到后端的根目录里面就行了

        如果要运行在其他路径下

build: {                          // config文件夹下index.js    (vue-cli项目)
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/project/',     //修改这里就可以使项目运行在后端的project路径下(当然要重新打包,然后把生成的dist目录修改成project)
           

59. 项目要请求其他端口或者域名下的接口数据:

module.exports = {      // config文件夹下index.js    (vue-cli项目)
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api':{
        target: 'http://localhost:80',        // 前端服务跑在8080端口,后端服务器是80 就改成80就可以了 (其他域名就被整个域名改掉)
        pathRewrite: {
          '^/api':'/static/mock/'   //这里要根据实际情况来改,如果接口本身就是/api 映射到 /api 那就可以把它去掉
        }
      }
    },
           

60. 行内设置样式

<div class="tiao" :style="{ width: item.jingdu}"></div>
           

61. router-link 标签上面绑定 @click会失效,要这样绑定 (只要是其他的组件标签都要加.native,原生类似 input这种标签绑定就不用)

<router-link tag="div" to="before" class="wangqi yiyang" @click.native="beforeClick">      // 加上.native
            <div :class="{ 'active': !isBenqi }">往期成绩</div>
        </router-link>
           

另外 router-link 标签上的 to='before'  就是把当前路由链接最后一个改成before,如果加上 to='/before' 就是 跳到 /before 的路径下

62. 获取当前页面的路由url地址用 : this.$route.path

63. vue.js 刷新页面 自动执行某个点击事件可以使用vue的生命周期函数,如create或者mounted

64. 在vue中使用 Clipboard.js  (页面复制文本到剪切板的)   

        git地址: https://github.com/zenorocha/clipboard.js

npm install clipboard --save

import Clipboard from 'clipboard'     // 引入

export default {
  name: 'Recharge',
  data () {
    return {
        clipboard:{},
        dizhi: '56565DFlfdgkdflgkdflgkldfgldfgdllfs44544'
    }
  },
  mounted () {
      this.clipboard = new Clipboard('.zi')     // 绑定要点击的那个按钮
      this.clipboard.on('success',function(e){        // 复制成功或者失败的事件
          alert("复制成功")
          e.clearSelection();
      });
      this.clipboard.on('error', function(e) {
        alert("复制失败!");
    });
  }
destroyed () {
      this.clipboard.destroy()    // 要在这里销毁,不然会弹出多次提示
  }
}
</script>
           
<div class="copy">
     <div class="zi" data-clipboard-target=".dizhi">一键复制</div>    //点击这个按钮,target那个属性是绑定要文本的目标
</div>
<div class="dizhi">{{dizhi}}</div>      // 要复制的文本的div
           

65. vue实现消息的无缝向上滚动效果: 参考 http://www.jb51.net/article/129733.htm   (亲测可用)

66. destroyed 这个生命周期表示切换页面后执行,可以在这销毁一些定时器事件等

destroyed () {
   window.clearInterval(this.timeID);  // 防止切换到其他组件页面报错
},
           

        (setInterval返回值相当于一个Id,每次执行都会产生一个特定的Id,返回值为数字,从一开始逐次累加,清除就是找到他            的id然后 clearInterval(id)就行了)

67. 想要为div加过渡动画就要用transition标签来包裹,vue会自动查看该元素的css来构建动画流程,name属性自定义

<transition name="fade">   // 如果name属性等于fade,那么样式里面的样式名前缀就是.fade-enter,如果不定义name属性,那么样式名前缀就是.v-enter
   <div v-if="show">hello world</div>
</transition>
           
.fade-enter {     隐藏到显示
   opacity: 0;
}
.fade-enter-active {
   transition: opacity 1s;
}
           

        vue会自动为标签加上这两个类名来做动画,我们只需要定义好类名的样式内容即可

.fade-leave-to{    显示到隐藏
   opacity: 0;
}
.fade-leave-active{
   transition: opacity 3s;
}
           

        如果我们想要显示到隐藏与隐藏到显示都有过渡效果,就可以把这些样式写在一起

.fade-enter,.fade-leave-to{   
   opacity: 0;
}
.fade-enter-active,.fade-leave-active{
   transition: opacity 3s;
}
           

68. vue中使用@keyframe这种css3的动画

@keyframes bounce-in{
   0%{
     transform: scale(0);
   }
   50%{
     transform: scale(1.5);
   }
   100%{
     transform: scale(1);
   }
}
.v-enter-active {
   transform-origin: left center;
   animation: bounce-in 1s;
}
.v-leave-active{
   transform-origin: left center;
   animation: bounce-in 1s reverse;
}
           

69. 在vue中使用animate.css库

<link...>  (引入animate.css库)
           
<transition 
   name="fade"
   enter-active-class="animated swing"
   leave-active-class="animated shake"   
>
   <div v-if="show">hello world</div>
</transition>
           

70. 加上 appear 和 appear-active-class 页面一刷新就有动画效果产生了(在引入animate库的前提下)

<transition 
   name="fade"
   appear
   enter-active-class="animated swing"
   leave-active-class="animated shake"   
   appear-active-class="animated swing"
>
   <div v-if="show">hello world</div>
</transition>
           

71. 插槽的使用(父组件向子组件传递DOM结构数据)

<body>
  <div>
    <child>
      <p slot='header'>header</p>   <p slot='footer'>footer</p>
    </child>
  </div>
  <script>
    Vue.component('child',{
      template: `<div>  <slot name='header'></slot>   //用这个来接收父组件传递过来的DOM结构
                  <p>hello</p>
                  <slot name='footer'></slot>   //用这个来接收父组件传递过来的DOM结构
                </div>`
    })
    ...
  </script>
           

72. 实现渐隐渐现效果的 vue-cli 中的可复用组件

<template>    //例如这个组件名文件名都叫 FadeAnimation
    <transition>
        <slot></slot>    
    </transition>
</template>
<script>
export default {
    name: 'FadeAnimation'
}
</script>
<style  scoped>
    .v-enter,.v-leave-to
        opacity: 0
    .v-enter-active,.v-leave-active
        transition: opacity .5s
</style>
           

哪个组件要用就引入以上组件然后用组件名包裹要渐隐渐现的元素

<fade-animation>
    <common-gallary :imgs="bannerImgs" v-show="showGallary" @close="handleGallaryClose"></common-gallary>
</fade-animation>
           

73. 项目完成想要真机调试时,使用localhost可以访问,使用内网ip地址访问不了,这是因为webpack-dev启动的项目默认不支持通过ip地址访问

74. 获取url上的?后面的参数用 

// 获取期号
let qi = this.$route.query.qi;
console.log(qi)
           

75. tab 标签页切换时给当前页面的标签添加样式

<router-link tag='div' to='/' class="home" exact> //注意:默认页即首页要加上 exact

<div class="ico">

<span class="iconfont">&#xe610;</span>

</div>

<div class="wenzi">竞猜</div>

</router-link>

<router-link tag='div' to='/my' class="hangqing">

<div class="ico">

<span class="iconfont"> &#xe619;</span>

</div>

<div class="wenzi">我的</div>

</router-link>

在app.vue 中加上

<style>

.router-link-active {

color: #fff //在这里填写你当前标签页的样式

}

</style>

76. Vant库的使用

        npm i vant -S  , npm i babel-plugin-import -D

        在.babelrc中配置

"plugins": [
    "transform-vue-jsx", 
    "transform-runtime",
    ["import",{"libraryName":"vant","style":true}]
  ]
           

        src/main.js

import { Button } from 'vant'
Vue.use(Button)
有了这段代码之后,我们就可以在需要的组件页面中加入Button了.

<van-button type="primary">主要按钮</van-button>
           

        如果不在src/main.js里加入代码,而在需要的页面单独引入:

<script>
import { Popup } from 'vant'
export default {
  name: 'HomeContent',
  components: {
    [Popup.name]: Popup
  },
           
<van-popup v-model="show" position="bottom" :overlay="false">
        内容
    </van-popup>
           

77. vue使用相对路径打包,可以直接打开(直接本地文件协议可以打开)丢给后台用:

        首先需要修改config/index.js文件:

build: {

// Template for index.html

index: path.resolve(__dirname, '../dist/index.html'),

// Paths

assetsRoot: path.resolve(__dirname, '../dist'),

assetsSubDirectory: 'static',

// assetsPublicPath: '/transaction/',

assetsPublicPath: './', //修改这里

        然后修改build/utils.js文件

if (options.extract) {

return ExtractTextPlugin.extract({

use: loaders,

fallback: 'vue-style-loader',

publicPath: '../../', //添加这一行

})

} else {

return ['vue-style-loader'].concat(loaders)

}

}

// https://vue-loader.vuejs.org/en/configurations/extract-css.html

return {

npm run build  即可打包成直接可以访问的文件了

78. 用vue 做語言切換: npm install vue-i18n

import VueI18n from 'vue-i18n' //vue-cli項目的main.js中這麼寫

Vue.use(VueI18n)

import LangEn from '../static/lang/en' // 引入配置的語言包,在static/lang文件夾下

// import LangZhCHS from '../static/lang/zhCHS'

import LangZhCHT from '../static/lang/zhCHT'

import LangYueNan from '../static/lang/yuenan'

const i18n = new VueI18n({

//定义默认语言

locale: 'Cn',

messages:{

'En': LangEn,

'Cn': LangZhCHT,

'Vn': LangYueNan

}

})

new Vue({ // 也是main.js 文件, 要掛載到Vue的實例上

el: '#app',

router,

i18n,

components: { App },

template: '<App/>'

})

在根目录下的static文件夹中新建lang文件夹,作为语言包
           
//en.js  語言包文件是這樣的  
module.exports={
  message: {
    hello: 'hello',
    about: 'about',
    welcome: "Welcome"
  }
}
           
//zhCHS.js
module.exports={
  message: {
    hello: '你好',
    about: '关于',
    welcome: "欢迎"
  }
}
           

在組件文件里的html上面是這麼用:{{ $t("message.hello") }}

在組件文件里的script裡面是這麼用: this.$t("message.welcome")

动态切换语言这样: this.$i18n.locale='CN'

79. 除了根组件,子组件想定义data必须要把它定义成一个函数

data () {
  return {
    content: "hello"
  }
}
           

80. vue 显示base64 的图片数据在页面上

<img :src="codeImg" class="img3" />

this.codeImg = "data:image/jpeg;base64,"+ msg.data.img

图片文件是什么格式就这里就写什么格式(png,jpeg等等)

81. vue中异步组件的使用,需要什么才加载什么,提高性能:   

import Vue from 'vue' //这是router里面的index.js文件

import Router from 'vue-router'

import Home from '@/pages/home/Home' //这一行删除掉

import My from '@/pages/my/My' //这一行删除掉

import Past from '@/pages/past/Past' //这一行删除掉

Vue.use(Router)

export default new Router({

routes: [

{

path: '/',

name: 'Home',

component: () => import('@/pages/home/Home') //修改这里

},

{

path: '/goals',

name: 'My',

component: () => import('@/pages/my/My') //修改这里

},

{

path: '/winner',

name: 'Past',

component: () => import('@/pages/past/Past') //修改这里

},

{

path: '/records',

name: 'Shuoming',

component: Shuoming

},

{

path: '/r

异步组件只有在app.js变得特别大(至少超过1mb)的时候才使用,其他情况就不需要考虑使用这种异步组件的形式,但是本人实践中发现有用还是好,首页加载快了很多

以上是在路由中使用异步组件,其他地方也可以用这种形式(父组件包含子组件的地方)

<template>

<div class="bg">

<home-shousuo :duizhanList="duizhanList" :yu_e="yu_e"></home-shousuo>

</div>

</template>

<script>

import HomeShousuo from './components/Shousuo' //这一行去掉

import axios from 'axios'

export default {

name: 'Home',

components: {

HomeShousuo: () => import('./components/Shousuo') //修改这里

},

这个异步组件的方式其实不一定要用,除非app.js真的很大才用,不然反而多了文件请求

vue