可以快速识别.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 create <project-name>
可以通过vue ui创建项目/管理项目依赖
vue ui
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'),
],
}
}
}
<template>
<div :id="`ball${_uid}`" class="ball" :style="{background:color}">
</div>
</template>
<script>
export default {
name:'ScrollBall',
props:{
color:{
type:String,
default:'red'
}
}
}
</script>
<style lang="less">
.ball{
width:80px;
height: 80px;
border-radius: 50%;
text-align:center;
line-height:80px;
}
</style>
<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>
<ScrollBall color="red" :target="500" v-model="pos">球1</ScrollBall>
<div :id="`ball${_uid}`" class="ball" :style="{background:color}">
<slot></slot>
</div>
<ScrollBall color="red" :target="500" v-model="pos1" ref="ball">球1</ScrollBall>
<button @click="stop">stop</button>
stop(){
this.$refs.ball.stopMove()
}
// 组件中停止小球运动
methods:{
stopMove(){
cancelAnimationFrame(this.timer);
},
move(){
let ele = document.getElementById(`ball${this._uid}`);
let left = this.value + 2;
if(left > this.target){
return this.stopMove();
}
ele.style.transform = `translate(${left}px)`;
this.$emit('input',left);
this.timer = requestAnimationFrame(this.move)
}
},
mounted(){
this.timer = requestAnimationFrame(this.move)
}
if(left > this.target){
this.$emit('end');
return this.stopMove();
}