快速原型开发 #

可以快速识别.vue文件封装组件插件等功能

sudo npm install @vue/cli -g
sudo npm install -g @vue/cli-service-global
vue serve Home.vue

关闭eslit提示

module.exports = {
    devServer: {
      overlay: {
        warnings: false,
        errors: false
      },
    }
}

实现递归菜单组件 #

<Menu>
    <MenuItem v-for="(item,key) in menuList" :key="key">
        {{item.title}}
    </MenuItem>
    <SubMenu>
        <template #title="title"> 标题1</template>
        <MenuItem>标题1-1</MenuItem>
        <MenuItem>标题1-2</MenuItem>
            <SubMenu>
            <template #title="title">标题1-1-1</template>
            <MenuItem>标题1-1-1-1</MenuItem>
            <MenuItem>标题1-1-1-1</MenuItem>
        </SubMenu>
    </SubMenu>
</Menu>

根据数据递归渲染

menuList:[
    {
        title:'标题1',
        children:[
            {title:'标题1-1'},
            {title:'标题1-2'}
        ]
    },
    {
        title:'标题2',
        children:[
            {title:'标题2-1'},
            {title:'标题2-2'}
        ]
    },
    {
        title:'标题3',
        children:[
            {title:'标题3-1'},
            {title:'标题3-2'}
        ]
    }
]

ReSub组件实现

<Menu>
    <template v-for="(item,key) in menuList" >
        <MenuItem v-if="!item.children" :key="key">
            {{item.title}}
        </MenuItem>
        <ReSub v-else :key="key" :data="item"></ReSub>
    </template>
</Menu>

// ReSub组件主要作用是递归
<template>
    <SubMenu class="sub">
        <template #title="title">{{data.title}}</template>
        <template v-for="d in data.children">
            <MenuItem v-if="!d.children" :key="d.title">{{d.title}}</MenuItem>
            <ReSub v-else :data="d" :key="d.title" class="sub"></ReSub>   
        </template>
    </SubMenu>
</template>

<script>
import SubMenu from './SubMenu';
import MenuItem from './MenuItem'
export default {
    props:['data'], 
    name:'ReSub',
    components:{
        SubMenu,
        MenuItem
    }
}
</script>

使用vue-cli3.0创建vue项目 #

vue create <project-name>

可以通过vue ui创建项目/管理项目依赖

vue ui

配置vue-config.js #

let path = require('path')
module.exports = {
    publicPath:process.env.NODE_ENV === 'production'? '/vue-project':'/',
    outputDir:'myassets', // 输出路径
    assetsDir:'static', // 生成静态目录的文件夹
    runtimeCompiler: true, // 是否可以使用template模板
    parallel:require('os').cpus().length > 1, //多余1核cpu时 启动并行压缩
    productionSourceMap:false, //生产环境下 不使用soruceMap

    // https://github.com/neutrinojs/webpack-chain
    chainWebpack:config=>{
        // 控制webpack内部配置
        config.resolve.alias.set('component',path.resolve(__dirname,'src/components'));
    },
    // https://github.com/survivejs/webpack-merge
    configureWebpack:{
        // 新增插件等
        plugins:[]
    },
    devServer:{ // 配置代理
        proxy:{
            '/api':{
                target:'http://a.zf.cn:3000',
                changeOrigin:true
            }
        }
    },
    // 第三方插件配置
    pluginOptions: {
        'style-resources-loader': {
            preProcessor: 'less',
            patterns: [
                // 插入全局样式
                path.resolve(__dirname,'src/assets/common.less'), 
            ],
        }
    }
}

defer & async / preload & prefetch #

基于vue-cli编写组件 #

小球的滚动组件 #

<ScrollBall color="red" :target="500" v-model="pos1"></ScrollBall> 
<ScrollBall color="blue" :target="300" v-model="pos2"></ScrollBall>

<script>
export default {
    props:{
        value:{
            type:Number,
            default:0
        },
        target:{
            type:Number,
            required:true
        }
    },
    mounted(){
        let ele = document.getElementById(`ball${this._uid}`);
        let timer;
        let fn = ()=>{
            let left = this.value + 2;
            if(left > this.target){
                return cancelAnimationFrame(timer);
            }
            ele.style.transform = `translate(${left}px)`;
            this.$emit('input',left);
            timer = requestAnimationFrame(fn)
        }
        timer = requestAnimationFrame(fn)
    }
}
</script>