Vue 项目起步
发布于: 2020 年 08 月 14 日
和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# ORyarn global add @vue/cli
创建一个新的Vue项目可以用如下命令:
vue create my-project
为了支持SASS和LESS预处理,需要安装如下库:
yarn add less-loaderyarn 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 } = thisreturn ['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 : nullreturn { 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 } = thisif (!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 } = thisif (!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.toggledif (!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 = falsenew Vue({ render: h => h(App),}).$mount('#app')
命令行输入yarn serve
划线
评论
复制
发布于: 2020 年 08 月 14 日阅读数: 80
JackWangGeek
关注
以匠人之精神,垒软件之砖 2020.01.10 加入
硕士,徐州软件协会副理事长,某创业公司合伙人
评论