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'); /* IE9*/

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

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

url('./iconfont/iconfont.ttf?t=1527149033233') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/

url('./iconfont/iconfont.svg?t=1527149033233#iconfont') format('svg'); /* iOS 4.1- */

}

例如:

<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 vue-awesome-swiper@2.6.7 -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 lang="stylus" 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 lang="stylus" 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真的很大才用,不然反而多了文件请求

        

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值