vue脚手架是一套工具的集合,有几个特性:
1.通过他可快速构建前端完整项目,里面包含服务器,之后通过脚手架里的服务器运行前端的代码。故和后台服务器访问是两个服务器访问,全是跨域请求。
2.编写前端项目时,每个页面是一个功能点,若有很多功能点就要写很多页面。脚手架里只需要一个页面,基于脚手架的前端应用都叫单页面应用。如何才能在一个页面显示不同的内容?先分析普通页面,body里是页面元素的代码,style里是样式代码,剩下就是javascript的代码。故只要提供这几份代码的编写位置,再用工具统一转成要使用的页面。
新建new_file.vue文件:
<template> </template> <script> </script> <style> </style>
template标签里写html元素,script标签里写javascript代码,style标签里写样式代码。
这种文件就是配合脚手架使用的。
之后会将一个个页面转成一个个vue文件,然后由脚手架控制替换到页面里。
3.页面里引入的东西很多,比如css,js,element,qs等等,而且引入的地址由自己控制。若前端项目比较多,这种依赖关系就很复杂,而且每个页面都得引入,重复引入多次。使用单页面的方式,引入的方式也会发生改变。
webpack工具提供了一种标准,按照标准进行项目编辑。

左边这种前端技术互相依赖,很杂乱的关系,通过webpack构建前端项目,会将依赖关系重新整理一份。实际真正访问时这些依赖关系就不存在了。
webpack规范代码结构的一套工具也集成在了脚手架里。
1.vue脚手架作用
前端开发需要的库文件很多,经常让前端工程的文件结构杂乱无章,并且容易产生代码重复,与工程化思维背道而驰,为了解决这个问题,通常使用webpack等项目构建工具,对使代码格式更规整,并且在js不断演化过程中出现了一些新语法方便编程,但是有一些语法浏览器并没有完全支持,所以出现了babel这种语法转换工具,把语法转换为浏览器可执行的语法。还有其他很多的一些工具,如果由开发人员手动安装、配置,很容易让项目文件结构变得混乱,难于配合。
由此产生的一系列问题,需要一套工程化,格式化的处理方案,就是脚手架,脚手架可以认为是一个工具集合,把常用的工具都集成起来,方便使用,并且使用工程化、模块化的思维,把文件存放的地址也进行了标准化,让开发人员开发时,文件、语法格式等都有章可循,那么项目开发过程中,多人配合时,代码结构与代码的可读性都会大幅提高。
此外脚手架基于node.js配置了Web服务器,及一些相关解析工具,利用npm(node包管理工具),可以非常方便的下载没有集成进去的额外的工具和包,对开发非常便利。
vue的脚手架便是把跟vue开发相关的一系列工具,以脚手架的方式整合起来,方便通过vue开发前端应用程序,其他前端框架也有对应的脚手架。
babel叫javascript的语法编译器,一种语法转换工具。现在使用的代码都是基于让浏览器能认识的javascript代码,但ES新的版本出了一些浏览器不认识(或者说只有高版本浏览器才能认出来)的代码。为了兼容所有浏览器,就出现了这个工具。

找一个下拉菜单的官方例子:
<el-dropdown>
<el-button type="primary">
更多菜单<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item>双皮奶</el-dropdown-item>
<el-dropdown-item>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown split-button type="primary" @click="handleClick">
更多菜单
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item>双皮奶</el-dropdown-item>
<el-dropdown-item>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<style>
.el-dropdown {
vertical-align: top;
}
.el-dropdown + .el-dropdown {
margin-left: 15px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
<script>
export default {
methods: {
handleClick() {
alert('button click');
}
}
}
</script>
上面放的html代码,中间放样式代码,下面放script代码。这个案例就是写单页面应用时脚手架里写代码的格式。
script标签里加了export default。export叫导出,还有个inport导入。
引入各种工具包括自己写的页面文件都会作为一个个组件来用,inport导入组件用。export导出组件用,要想在别的组件使用,就写export default,并且导出以当前vue默认的文件名导出。
2.安装
脚手架安装依赖于node.js 里的一个包安装工具,叫npm。库文件的引入除了cdn加速服务引入的方式外,还可使用npm命令安装:
npm i element-ui -S
npm有远程仓库,本地有npm这样一个包管理工具后,直接敲命令,它会找到配置的远程仓库的地址,将依赖的库文件直接下载到本地。
npm 的方式安装,它能更好地和 webpack 打包工具配合使用。
npm包安装工具是集成在node.js 里的,故先安装node.js。(不是为了用node.js,而是用它里面的npm。)
(node.js是从谷歌的Chrome浏览器里把内核,即V8引擎抽出来,做一些本地的IO)
2.1安装node和npm
一系列工具都是基于node.js,所以首先需要安装node.js,node的包管理工具npm会随node安装包一起安装。
官网地址:Node.js
安装完成后,需要修改npm下载路径(默认服务器在国外 速度较慢) 改为淘宝镜像(国内镜像服务器 速度快)
2.2配置npm服务器地址(运行cmd 再在命令行输入)
临时使用 npm --registry https://registry.npm.taobao.org install express
永久使用 直接配置 npm config set registry https://registry.npm.taobao.org
通过如下命令可以查看是否配置成功 npm config get registry npm info express
如果需要恢复成原来的官方地址只需要执行如下命令: npm config set registry https://registry.npmjs.org
2.3安装vue脚手架
通过npm命令 安装vue脚手架(vue/cli,输入Vue CLI可查看官网)
npm install -g @vue/cli(还是在控制台敲)

左边是进度条,安装需要些运气。过程中卡住,安装失败,就重新敲命令去安装。
等待安装完成,需要时间较长 安装完成后可以通过命令行检查是否安装完成
vue -V 查看vue版本(不是vue本身的版本,是脚手架的版本)
2.4创建vue项目
安装完成后,可以使用vue脚手架创建项目结构,有如下两种方式:
vue ui vue图形界面(功能强大 操作方便)
(vue create my-project 命令行创建,官网会写有哪些命令去做)
2.5启动图形界面创建
这里使用vue图形界面,控制台输入vue ui,会弹出Vue管理器。
vue图形界面包括创建项目、安装依赖、安装插件、运行控制台等功能,可以方便的进行相关控制
进入图形界面项目管理器 可以创建vue项目
①.点击创建
②.在D盘新建myproj目录,点击笔图标,将目录地址输入

③.点击在此创建新项目,出现如下页面

④.起一个当前项目名proj1。包管理器选择npm(默认也是使用npm)。点击下一步。出现下面界面

⑤.选择手动,下一步。出现如下界面:
手动配置时注意选项:

Babel必选。
Router路由,单页面应用必须有。
Linter/Formatter,js语法检测工具,语法有问题会提示。不是写代码时提示,启动服务器时提醒。但过于严格,空格都不能多打,不选。
使用配置文件也选。
点击下一步。
出现这个界面

⑥.勾选2x,现在使用的还是2版本
使用历史模式还是路由模式,不选。
点击创建项目。

选择中间的。
然后控制台安装,脚手架创建的项目为独立运行项目,会把node依赖的相关环境也现在,需要等待一会。

创建成功会进入项目仪表盘

2.6启动服务

点击启动app,默认8080,若8080端口被占用,会自动往后移。
关于创建的proj1项目的目录结构:

将该目录拖到HBUilder里,见下。
3.导入vue项目到编辑工具
vue项目目录结构如下

node_modules目录,存放项目依赖的工具包。
public目录里是公共的部分,即单页面应用里的唯一一个页面index.html。
src是编写代码的地方
剩下的是项目的配置文件,主要用package.json,有项目的描述信息和依赖的一些库名。
接下来配置端口号,默认走8080,和Tomcat有点冲突。若Tomcat先启动,它端口号往后移动,若它先启动,Tomcat就不能启动。在vue.config.js里添加如下代码:
module.exports = {
devServer: {
port: 8088, // 端口
}
}
现在HBUilder只是充当文本编辑工具。编译和运行都是脚手架。
看一下src目录

main.js(入口文件)里:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
通过impot导入要引用的组件。之后创建vue对象,并.$mount('#app')。app就在public目录的index.html页面。
在App.vue里:
<template> <div> abc123 </div> </template> <style> </style>
回到任务,点击停止,再点击运行(重新部署),再点击启动app,页面出现abc123
注:在vue文件里写内容,写在template标签。但该标签要有根标签,同时不能有同级标签,否则编译不通过。
错误示例:
<template> abc123 </template>
<template> <div> abc123 </div> <div> def567 </div> </template>
这是脚手架基本规则之一。
4.安装插件和依赖
开发vue项目时 还需要安装在项目中使用的一些额外的包,分别有插件和依赖
(要安装到当前项目的node_modules目录。使用图像界面会自动安装到该目录下)
到项目仪表盘 ,点击依赖

点击右上角+安装依赖。找axios,点击安装。控制台会进行安装。(相当于在当前项目的当前目录里敲击了nmp的安装命令)
再安装Qs。
点击插件(集成程度更高),安装elementUI插件
下载这个vue-cli-plugin-element
5.整理项目结构
安装插件和依赖后,App.vue 又变回去了。
再次将里面没用的删掉:
<template> <div> abc123 </div> </template> <script> </script> <style> </style>
图形界面有热部署,即修改完HBUilder的代码保存以后,页面就自动改变了,不需要重新部署。
但新建了文件需要重新部署。
src的assets目录里放的图片。
src的components目录放的HelloWorld.vue,用不着,是欢迎项目,删掉。
src的router目录里有index.js是路由的配置文件,也删除没用的:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
/* {
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" '../views/AboutView.vue')
} */
]
const router = new VueRouter({
routes
})
export default router
src的views里是刚才欢迎页面里导入的两个elementUI组件,主要是通用的显示功能,也删掉。
现在,项目结构干净了,只有必要的配置文件(index.js),入口文件(main.js)和根组件(App.vue)
6.自己加组件
①.加组件在前端服务器运行
在src的components目录下创建mypage.vue
<template>
<div>
mypage
</div>
</template>
<script>
</script>
<style>
</style>
在App.vue
<template> <router-view></router-view> </template> <script> </script> <style> </style>
router就是替换代码块的工具,router-view意思就是路由显示在这。
(有组件都显示在这里)
另外,在router目录的index.js里,将路由配置进去:
先用import引入组件,Mapage是给组件起的名字,习惯首字母大写。from后是路径
import Mapage from '../components/mypage.vue'
const routes = [
{path:'/mypage',component:Mapage}
]
const router = new VueRouter({
routes
})
export default router
在vue图形界面的浏览器输入:
http://localhost:8088/#/mypage
页面显示:mypage
②.再加一个组件
新建src.components.loginPage.vue(准备组件)
<template>
<div>
loginpage
</div>
</template>
<script>
</script>
<style>
</style>
App.vue不动(组件都来这里)
在src.router.index.js里配置路由地址(import加一个,再加一组path,component)
import Vue from 'vue'
import VueRouter from 'vue-router'
import Mapage from '../components/mypage.vue'
import Login from '../components/loginPage.vue'
Vue.use(VueRouter)
const routes = [
{path:'/mypage',component:Mapage},
{path:'/login',component:Login}
/* {
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" '../views/AboutView.vue')
} */
]
const router = new VueRouter({
routes
})
export default router
保存,访问:http://localhost:8088/#/login
页面显示:loginpage
const routes = [
{path:'/mypage',component:Mapage},
{path:'/login',component:Login},
{path:'/',redirect:"/login"}
]
此时页面直接显示:loginpage
③.将之前做的登录页面的内容拉到loginPage.vue
注:javascript的内容要符合规则,即要有export default
el部分不需要,vue也不需要了。
<template>
<div>
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="myform" :rules="rules" :model="form" label-width="80px" hide-required-asterisk>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">登录</el-button>
<el-button @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</template>
<script>
export default {
methods: {
mySubmit(){
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
//后台服务接口返回登录成功
location.href = "mainPage.html";
} else {
console.log('数据有误 不能提交');
return false;
}
});
},
resetForm(formName) {
this.$refs['myform'].resetFields(); //通过this.$refs['myform']找到组件,调用resetFields方法清空数据
}
},
data () {
return {
form: {
username: '',
userpwd:''
},
rules: {
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
};
}
}
</script>
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
.mycard{
margin:240px auto;
}
</style>
④.将主页面也拉进来
新建mainPage.vue
<template>
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<el-col :span="24">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<!--给不同用户展示不同的菜单,主要功能点还是在后台,后台根据用户的权限给前台准备好查询菜单的服务接口-->
<el-submenu v-for="menu in menuList" :index="menu.menuid">
<template slot="title">
<i class="el-icon-document"></i>
<span>{{menu.menuname}}</span>
</template>
<el-menu-item v-for="subm in menu.submenu" :index="subm.menuid">{{subm.menuname}}</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
},
data () {
return {
menuList:[{"menuid":"11","menuname":"系统管理","icon":"el-icon-s-tools","submenu":
[{"menuid":"11001","menuname":"系统参数"},
{"menuid":"11002","menuname":"系统参数"},
{"menuid":"11003","menuname":"系统参数"}]},
{"menuid":"12","menuname":"用户管理","icon":"el-icon-s-phone","submenu":
[{"menuid":"12001","menuname":"用户入职"},
{"menuid":"12002","menuname":"用户离职"}
]}]
};
}
}
</script>
<style>
html,body{
height:100%;
width:100%;
margin:0px ;
padding:0px;
}
#app{
height:100%;
}
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
body > .el-container {
margin-bottom: 40px;
/* height:100%; 这里也加个样式,后来发现不生效,说明被覆盖 */
}
body .el-container {
height:100%;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>
index.js中配置路由:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Mapage from '../components/mypage.vue'
import Login from '../components/loginPage.vue'
import Main from '../components/mainPage.vue'
Vue.use(VueRouter)
const routes = [
{path:'/mypage',component:Mapage},
{path:'/login',component:Login},
{path:'/main',component:Main},
{path:'/',redirect:"/main"}
/* {
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" '../views/AboutView.vue')
} */
]
const router = new VueRouter({
routes
})
export default router
考虑,登录成功后跳转到主页面,就不能使用
location.href = "mainPage.html";
因为只有一个页面,要用到:
this.$router.push("/main");
意思是主动使用路由跳转。
⑤.qs,axios的使用
这里报错了,Qs直接使用会出错。使用脚手架方式后,应在script标签第一行导入qs:
import qs from 'qs'
然后在将
console.log(window.Qs.stringify(this.form));
改为:
console.log(qs.stringify(this.form));
但这种方式很麻烦,
另一种方式,入口文件main.js每次都会优先执行它,通过它创建vue对象,故可在这里引入qs。
导入一次,想在其他组件使用,可给vue对象扩展属性
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
import qs from 'qs'
Vue.config.productionTip = false
//prototype 原型链,可以拿到js对象的各种构造,属性,方法,也可对当前对象修改
Vue.prototype.$qs = qs; //将引入的qs组件注册给了vue组件,变成了vue对象的通用功能
(找到了vue对象的原型链,对现在已经创建出的对象扩展出一个qs属性,qs属性指向引入的qs组件)
new Vue({
router,
render: h => h(App)
}).$mount('#app')
之后在其他组件需要用到qs的地方:
console.log(this.$qs.stringify(this.form));
this代表vue对象,$自己注册的东西。
对于axios是一样的。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
import qs from 'qs'
import axios from 'axios'
Vue.config.productionTip = false
Vue.prototype.$qs = qs;
Vue.prototype.$axios = axios;
new Vue({
router,
render: h => h(App)
}).$mount('#app')
对于登录页面:
<template>
<div>
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="myform" :rules="rules" :model="form" label-width="80px" hide-required-asterisk>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">登录</el-button>
<el-button @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</template>
<script>
export default {
methods: {
mySubmit(){
//$refs 注册给vue的组件
console.log(this);
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(this.$qs.stringify(this.form));
console.log(this.$axios.get("/xxxx").then((ret)=>{}).catch((err)=>{}));
//axios.get("/xxxx").then((ret)=>{}).catch((err)=>{})
//console.log(window.Qs.stringify(this.form));
//后台服务接口返回登录成功
/* location.href="mainPage.html"; */
//主动使用路由跳转
//this.$router.push("/main");
} else {
console.log('数据有误 不能提交');
return false;
}
});
},
resetForm(formName) {
this.$refs['myform'].resetFields(); //通过this.$refs['myform']找到组件,调用resetFields方法清空数据
}
},
data () {
return {
form: {
username: '',
userpwd:''
},
rules: {
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
};
}
}
</script>
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
.mycard{
margin:240px auto;
}
</style>
7.解决Vue乱码问题
后端编码格式是utf-8,前端前端格式也是utf-8。
昨天不知是何原因,新建的一个组件(vue文件)编码格式设置成了GBK格式。做完逻辑功能后页面显示乱码。
这里用简单的例子,解决乱码问题:
如下:

右下角是gbk。(注:其他组件还是utf-8)
需要变回utf-8才不会出错。
试过的几种错误做法:
①.右下角直接改成utf-8
(配置该组件的编码格式,其他不影响)
②.左上角文件--->以指定编码格式重新打开,选择utf-8
(这个是配置整个程序的编码格式,不过其他的文件都是utf-8)
③.打开public目录下的index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
改里面的编码格式为gbk,即解析时以utf-8格式解析。
(这个改法就严重了,它的效果等同于②,一改其他的文件全都受到影响,怎么影响?
其他文件用utf-8格式写好了代码,这一改,解析的时候都得乱码)
④.将后端发送数据时的响应头改成gbk格式
首先后端以utf-8编码格式写的代码,发的代码又是另一个编码格式,必乱码。
①,②改了,这个组件立马变乱码。用GBK写完了,才改成utf-8格式,自然乱码。
正确做法:
将该组件里的内容复制一份,打开Notepade++,以记事本方式打开,粘贴进去,另存为时,将编码格式改成utf-8。(直接打开记事本就行,装了Notepade++,记事本就被它覆盖了)
回到乱码的组件,先把内容全删除,再右下角改成utf-8。
最后将记事本的代码复制进来即可。
本文详细介绍了Vue脚手架的作用、安装过程、项目创建与配置,包括Vue CLI的使用、模板结构、单页面应用原理、组件编写、路由配置、依赖管理以及热部署。还展示了如何通过Vue CLI创建项目,安装并使用Element UI,以及解决编码乱码问题的方法。通过实例演示了Vue项目的结构、组件化开发和axios的使用。
Vue脚手架&spm=1001.2101.3001.5002&articleId=124829626&d=1&t=3&u=d86aec8e91f545e0bf0cf1896d8c52f2)

被折叠的 条评论
为什么被折叠?



