vue项目技术小记

最近做的项目快要结尾了,本项目用前后端分离的,然后前端是用vue开发的,为什么选vue呢?一来公司要求效率要高些的,那就应该用到三大流行的框架之一,然后项目的内容不太复杂的,觉得用vue更合适的。二来正好应该要“炒熟”vue了哈。其中陷入了不少坑,一个一个爬过来的,总结下入坑的原因,另外会给出官方文档的对应内容,以便加深理解的。如有不足之处,请提出来哈~

  • 异步加载组件

    • 我们都知道vue一般都是单页面的,也就意味着一开始就要加载全部的组件,这太不友好的,加载时间会慢些。这时候我们就用到异步组件~
    const Index=()=>import('@/page/Index');
    const Home=()=>import('@/page/Home');
    const router=new Router({
        routes:[
        {
            path:'/index',
            component:Index
        },
        {
            path:'/home',
            component:Home
        }
        ]
    })
    

    然后你会发现js被分开的,这就是所谓的异步加载~

  • 在相同路由的情况下,再次点击导航栏上的本路由,再次刷新

    在vue中,路由地址相同的情况下,是不会再次刷新的,即使点击本路由的导航文字上。一开始我没想到解决的方案,后来寻求大佬商量,大佬说可以用事件传递的。然后他告诉我一句话的,

    vue.js一定不会阻碍传统方法实现的。

    这话说得我惭愧,我意识到我太依赖vue.js的框架,没拓展思维的。再次感谢大佬的点拔~

    • 对,是可以用事件传递来实现的。在主路由上绑定isFresh,判断需不需要刷新子路由,然后在子路由上绑定事件,传递到主路由的事件。主路由监听到事件的,就把isFresh变为false,以防下面还会需要到。不设置为false,下面的就不会刷新。看代码如下:
    • App.vue
    <router-view :isFresh="isFresh" @tempBtn="tempBtn"/>
    //data
    data(){
        return {
            isFresh:false,
        }
    }
    //事件函数
    tempbtn(){
        this.isFresh=false;
    }
    
    • Index.vue
    watch:{
        isFresh(){
            //console.log('ShopisFresh:'+this.isFresh);
            if(this.isFresh){
                Object.assign(this.$data,this.$options.data());
                this.fetchData();
            }
        }
    },
    //然后加载完后,还要绑定事件,传递到主路由的tempbtn事件
    this.$emit('tempbtn');
    

    嗯,在子路由上监听到isFresh为true,表示要刷新的,Object.assign是利用data的初始化数据覆盖,然后重新加载数据。

  • checkbox整体点击

    UI设计师要求能点击checkbox的整体,包括checkbox后面的文字,不是只能点击checkbox的框,这可把我为难了,然后艰难的爬出坑了。

    <div class="group_item" @click="selfChecked = !selfChecked">
        <input type="checkbox" v-bind:checked="selfChecked">
        <label>点我呀</label>
        data(){
            return {
                tempChecked:null
            }
        },
        props:['checked'],
        watch:{
            checked(){
                this.tmpChecked=this.checked
            }
        },
        computed: {
            selfChecked: {
                get: function(val){
                    return this.tmpChecked;
                },
                set: function(newVal){
                    this.tmpChecked = newVal
                    this.$emit('input', newVal)
                }
            }
        },
    </div>
    

    然后在父组件上用v-model即可。用selfChecked来判断是不是要点击,至于为什么要watch,是判断checked为真还是假,比如说在父组件上,提交后,表单要清空的,这时候要监听到checked为假的,然后传递到selfChecked的值。这样就能清空checkbox。

  • setInterval的问题

    用了setInterval之后,切换路由的时候发现还在计时,不得了,真的会影响性能唉,就吓的赶紧啃官方文档,找到了~

    beforeDestroy(){
        clearInterval(this.interId);
    }
    

    beforeDestroy是毁路由之前的函数,就是说毁路由之前就清除setInterval

    • 参考vue的生命周期
  • 在v-for循环中进行v-model数据绑定

    <div v-for="(item,index) in list">
        <textarea type="text" v-model="list[index]['content']"></textarea>
    </div>
    

下面说说和vue没关系的问题

  • 上线时去掉console

    我们一般都会用console来打印,以便检查的,万一console写多了,上线时总不能打印出console吧,要注释掉,但太费时间吧,这时候webpack神器上场(本人用webpack3)

    • 在webpack.prod.config.js中
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false,
          drop_debugger: true,
          drop_console: true
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
    }),
    

    这prod是生产环境的,然后drop_console为true,是去掉console

  • 兼容ie的问题

    部署到生产环境后,测试ie11时发现空白屏的,我慌了,不是说可以兼容到ie9吗?还是说没配置好的,然后google查,ie还没支持js新的api,比如promise,所以需要babel-polyfill来转换的。真是蛋疼的ie,还能怎么办呢?当然是加babel-polyfill插件的。

    npm install babel-polyfill --save
    //然后在webpack.base.config.js中引用这插件
    module.exports=require('babel-polyfill');
    module.export={
        ...
        entry:{
            app:['babel-polyfill','./src/main.js']
        }
    }
    
  • 打包第三方库

    打包时把第三方库合并成vendor.js,但是这个vendor.js有hash,这就意味着每次打包时vendor.js的hash会变化的,然后在浏览器会重新加载。vendor.js的代码本来就很少被改变的,重新加载就影响加载时间的。从目前搜索的解决方案,比较好的方案有两种:
    1、 第一种用dll来打包的,webpoack自带的

    • 首先在build里新建一个文件,命名为webpack-dll.config.js
    const webpack=require('webpack')
    const path=require('path')
    
    module.export={
        entry:{
            vendors:['vue.js','axios','vue-router','vuex','vue/dist/vue.esm.js']   //加入要打包的第三方库
        },
        output:{
            filename:'[name].dll.js',  //输入的文件名
            path:'path.join(__direname,'../static')',   //输入的路径
            library:'[name]'
        },
        plugin:[  //为了和第三方库的dll.js对应,build时不会把这个打包进去,就是说能减少build构建的时间
            new webpack.DllPlugin({
                path:path.join(__direname,'../','[name]-mainfest.json'),  //输入的mainfest文件的路径
                name:'[name]'
            })
        ]
    }
    
    • 然后命令生成vendor-mainfest.json
    //在package.json添加一行
    "dll":"webpack --config build/webpack.dll.config.js"
    

    然后npm run dll,就生成vendor-mainfest.json

    • 然后还要在webpack.base.conf.js配置,改变构建的配置
    //添加一行
    const mainfest=require('../vendors-mainfest.json')  //
    //在module.exports添加配置
    module.exports={
        ...
        plugins:[
            new webpack.DllReferencePlugin({
                mainfest
            })
        ],
        ...
    }
    

    然后把CommonsChunkPlugin的这块注释掉,不然要重复打包。

    • 最后在index.html加上一行
    <script src="./static/vendors.dll.js"></script>
    
    2、 第二种方案就是用bootcdn
    
    原文作者:Fernweh_Nancy
    原文地址: https://www.jianshu.com/p/454600e7aba9
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞