赞
踩
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规范代码结构的一套工具也集成在了脚手架里。
前端开发需要的库文件很多,经常让前端工程的文件结构杂乱无章,并且容易产生代码重复,与工程化思维背道而驰,为了解决这个问题,通常使用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默认的文件名导出。
脚手架安装依赖于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里,见下。
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>
这是脚手架基本规则之一。
开发vue项目时 还需要安装在项目中使用的一些额外的包,分别有插件和依赖
(要安装到当前项目的node_modules目录。使用图像界面会自动安装到该目录下)
到项目仪表盘 ,点击依赖
点击右上角+安装依赖。找axios,点击安装。控制台会进行安装。(相当于在当前项目的当前目录里敲击了nmp的安装命令)
再安装Qs。
点击插件(集成程度更高),安装elementUI插件
下载这个vue-cli-plugin-element
安装插件和依赖后,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)
①.加组件在前端服务器运行
在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>
后端编码格式是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。
最后将记事本的代码复制进来即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。