写点什么

Vue 项目起步

用户头像
JackWangGeek
关注
发布于: 2020 年 08 月 14 日
Vue项目起步

和React类似,Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

当前的Web应用越来越复杂,前端的代码也越来越庞大,目前可以说前端开发已经步入工程化阶段。当React和Vue出现后,UI组件越来越丰富。Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。

当我们开始学习Vue时,可以通过官方的CLI工具作为起步。Vue CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。只需要几分钟的时间就可以运行起来并带有热重载、保存时Lint 校验,以及生产环境可用的构建版本。

访问网址https://cli.vuejs.org/zh/即可查看相关Vue CLI的详细说明。安装此CLI可以用如下命令:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

创建一个新的Vue项目可以用如下命令:

vue create my-project

为了支持SASS和LESS预处理,需要安装如下库:

yarn add less-loader
yarn add sass-loader

创建如下项目结构:

package.json内容如下:

{
"name": "my-vue-demo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"less-loader": "^6.2.0",
"sass-loader": "^9.0.3",
"vue": "^2.6.11"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.14.1",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

webpack.config.js

var path = require('path')
var webpack = require('webpack')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'main.js',
libraryTarget: 'umd'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': 'vue-style-loader!css-loader!sass-loader'
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
externals: {
vue: 'vue'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
performance: {
hints: false
},
devtool: '#source-map',
plugins: [
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
})
]
}

ToggleButton.vue

<template>
<label
:class="className"
tabindex="0"
role="checkbox"
@keydown.space.prevent="keyToggle"
>
<input
type="checkbox"
class="v-switch-input"
:name="name"
:checked="value"
:disabled="disabled"
tabindex="-1"
@change.stop="toggle"
/>
<div class="v-switch-core" :style="coreStyle">
<div class="v-switch-button" :style="buttonStyle" />
</div>
<template v-if="labels">
<span class="v-switch-label v-left" :style="labelStyle" v-if="toggled">
<slot name="checked">
<template>{{ labelChecked }}</template>
</slot>
</span>
<span class="v-switch-label v-right" :style="labelStyle" v-else>
<slot name="unchecked">
<template>{{ labelUnchecked }}</template>
</slot>
</span>
</template>
</label>
</template>
<script>
import { isString, isObject, isBoolean, has, get, translate, px } from '../utils'
const DEFAULT_COLOR_CHECKED = '#65c791'
const DEFAULT_COLOR_UNCHECKED = '#bfced9'
const DEFAULT_LABEL_CHECKED = 'on'
const DEFAULT_LABEL_UNCHECKED = 'off'
const DEFAULT_SWITCH_COLOR = '#fffff'
export default {
name: 'ToggleButton',
props: {
value: {
type: Boolean,
default: false
},
name: {
type: String
},
disabled: {
type: Boolean,
default: false
},
tag: {
type: String
},
sync: {
type: Boolean,
default: false
},
speed: {
type: Number,
default: 300
},
color: {
type: [String, Object],
validator(value) {
return (
isString(value) ||
has(value, 'checked') ||
has(value, 'unchecked') ||
has(value, 'disabled')
)
}
},
switchColor: {
type: [String, Object],
validator(value) {
return (
isString(value) || has(value, 'checked') || has(value, 'unchecked')
)
}
},
cssColors: {
type: Boolean,
default: false
},
labels: {
type: [Boolean, Object],
default: false,
validator(value) {
return typeof value === 'object'
? value.checked || value.unchecked
: typeof value === 'boolean'
}
},
height: {
type: Number,
default: 22
},
width: {
type: Number,
default: 50
},
margin: {
type: Number,
default: 3
},
fontSize: {
type: Number
}
},
computed: {
className() {
let { toggled, disabled } = this
return [
'Toggle-Button',
{
toggled,
disabled
}
]
},
coreStyle() {
return {
width: px(this.width),
height: px(this.height),
backgroundColor: this.cssColors
? null
: this.disabled
? this.colorDisabled
: this.colorCurrent,
borderRadius: px(Math.round(this.height / 2))
}
},
buttonRadius() {
return this.height - this.margin * 2
},
distance() {
return px(this.width - this.height + this.margin)
},
buttonStyle() {
const transition = `transform ${this.speed}ms`
const margin = px(this.margin)
const transform = this.toggled
? translate(this.distance, margin)
: translate(margin, margin)
const background = this.switchColor ? this.switchColorCurrent : null
return {
width: px(this.buttonRadius),
height: px(this.buttonRadius),
transition,
transform,
background
}
},
labelStyle() {
return {
lineHeight: px(this.height),
fontSize: this.fontSize ? px(this.fontSize) : null
}
},
colorChecked() {
let { color } = this
if (!isObject(color)) {
return color || DEFAULT_COLOR_CHECKED
}
return get(color, 'checked', DEFAULT_COLOR_CHECKED)
},
colorUnchecked() {
return get(this.color, 'unchecked', DEFAULT_COLOR_UNCHECKED)
},
colorDisabled() {
return get(this.color, 'disabled', this.colorCurrent)
},
colorCurrent() {
return this.toggled ? this.colorChecked : this.colorUnchecked
},
labelChecked() {
return get(this.labels, 'checked', DEFAULT_LABEL_CHECKED)
},
labelUnchecked() {
return get(this.labels, 'unchecked', DEFAULT_LABEL_UNCHECKED)
},
switchColorChecked() {
return get(this.switchColor, 'checked', DEFAULT_SWITCH_COLOR)
},
switchColorUnchecked() {
return get(this.switchColor, 'unchecked', DEFAULT_SWITCH_COLOR)
},
switchColorCurrent() {
let { switchColor } = this
if (!isObject(this.switchColor)) {
return this.switchColor || DEFAULT_SWITCH_COLOR
}
return this.toggled ? this.switchColorChecked : this.switchColorUnchecked
}
},
watch: {
value(value) {
if (this.sync) {
this.toggled = !!value
}
}
},
data() {
return {
toggled: !!this.value
}
},
methods: {
keyToggle(event) {
if (this.disabled) {
return
}
this.toggle(event)
},
toggle(event) {
const toggled = !this.toggled
if (!this.sync) {
this.toggled = toggled
}
this.$emit('input', toggled)
this.$emit('change', {
value: toggled,
tag: this.tag,
srcEvent: event
})
}
}
}
</script>
<style lang="scss" scoped>
.Toggle-Button {
display: inline-block;
position: relative;
vertical-align: middle;
user-select: none;
font-size: 10px;
outline:none; //去掉单击黑色边框
border: 0;
cursor: pointer;
.v-switch-input {
opacity: 0;
position: absolute;
width: 1px;
height: 1px;
}
.v-switch-label {
position: absolute;
top: 0;
font-weight: 600;
color: white;
z-index: 1;
&.v-left {
left: 10px;
}
&.v-right {
right: 10px;
}
}
.v-switch-core {
display: block;
position: relative;
box-sizing: border-box;
outline: 0;
margin: 0;
transition: border-color 0.3s, background-color 0.3s;
user-select: none;
.v-switch-button {
display: block;
position: absolute;
overflow: hidden;
top: 0;
left: 0;
border-radius: 100%;
background-color: #fff;
z-index: 2;
}
}
&.disabled {
pointer-events: none;
opacity: 0.6;
}
}
</style>

App.vue

<template>
<div id="app">
<ToggleButton/>
</div>
</template>
<script>
import ToggleButton from './components/ToggleButton.vue'
export default {
name: 'App',
components: {
ToggleButton
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>



main.js

import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')

命令行输入yarn serve







用户头像

JackWangGeek

关注

以匠人之精神,垒软件之砖 2020.01.10 加入

硕士,徐州软件协会副理事长,某创业公司合伙人

评论

发布
暂无评论
Vue项目起步