Vue cli是基于Vue的应用开发提供的一个标准的脚手架工具.为应用搭建基础的框架结构,提供插件、开发服务、Preset、构建打包功能
Vue cli 背后集成了现代化开发的诸多功能,通过简单的命令就可以完成 "零配置"的项目环境搭建
在安装vue-cli前,要确认自己的电脑是否安装了nodejs和npm.
安装了node.js才有使用npm ,才能安装vue-cli
为什么会有node.js?
传统意义上的 JavaScript 运行在浏览器上,Chrome 使用的 JavaScript 引擎是 V8,Node.js 是
一个运行在服务端 的框架,它的底层就使用了 V8 引擎,这样就可以使用javascript去编写一些服
务端的程序,这样也就实现了用 javaScript去开发 Apache + PHP 以及 Java Servlet所开发的服务
端功能,这样做的好处就是前端和后端都采用 javascript,即开发一份js程序即可以运行在前端也
可以运行的服务端,这样比一个应用使用多种语言在开发效率上 要高,不过node.js属于新兴产
品,一些公司也在尝试使用node.js完成一些业务领域,node.js基于V8引擎,基于 事件驱动机
制,在特定领域性能出色,比如用node.js实现消息推送、状态监控等的业务功能非常合适。
node -v //会显示当前node的版本
npm全称Node Package Manager,他是node包管理和分发的工具,使用NPM可以对应用的依赖进
行管理,NPM 的功能和服务端项目构建工具maven的依赖管理功能差不多,我们通过npm 可以很方便地下载js库,打包js文件。
node.js已经集成了npm工具
在命令提示符输入 npm -v 可查看当前npm版本
npm -v
包路径就是npm从远程下载的js包所存放的路径。 使用 npm config ls 查询NPM管理包路径(NPM
下载的依赖包所存放的路径)
npm config ls
我们发现NPM默认的管理包路径在:
C:\Users\86187\AppData\Roaming\npm
依赖包放在C盘不太合适,为了方便对依赖包管理, 我们将管理包的路径设置在单独的地方:
npm config set prefix "H:\software\nodejs_package\npm_modules"
npm config set cache "H:\software\nodejs_package\npm_cache"
npm config get prefix
npm默认会去国外的镜像去下载js包,在开发中通常我们使用国内镜像,这里我们使用淘宝镜像下边我们来安装cnpm: 有时我们使用npm下载资源会很慢,所以我们可以安装一个cnmp(淘宝镜像)来
加快下载速度。
//安装
npm install -g cnpm --registry=https://registry.npm.taobao.org
//查看cnpm的版本
cnpm -v
目前主流版本是 2.x 和 3.x 版本,安装3.x 以上的版本是因为该版本既可以创建2.x项目与3.x 项目
注意: 以管理员身份打开命令行
版本卸载或调整:https://blog.csdn.net/weixin_43279985/article/details/104841143
npm install -g @vue/cli
vue -V
我们使用vue-cli 快速构建项目,步骤如下:
1.基于交互式命令方式,创建项目
//文件名 不支持驼峰(含大写字母)使用短横线方式
vue create my-project
首先进入项目目录
cd my-project
npm run serve
1.VSCode中右键选择打开文件夹
2.选择桌面上的项目
3.打开项目,可以看到如下项目结构
|--- my-project 项目名称
|--- node_modules 存放依赖包的目录
|--- public 静态资源管理目录
|--- src 组件源码目录(我们写的代码)
|--- assets 存放静态图片资源(CSS也可以放在这里)
|--- components 存放各种组件(一个页面可以看做一个组件),各个组件联系在一起组成一个 完整的项目
|--- router 存放了项目路由文件
|--- views 放置的为公共组件(主要还是各个主要页面)
|--- App.vue app.vue可以当做是网站首页,是一个vue项目的主组件,页面入口文件
|--- main.js 打包运行的入口文件,引入了vue模块和app.vue组件以及路由route
|--- babel.config.js babel配置文件, 对源代码进行转码(把es6=>es5)
|--- package.json 项目及工具的依赖配置文件
|--- paxkage-lock.json 依赖配置文件
|--- README.md 项目说明
每个项目的根目录下面,一般都有一个 package.json 文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。 npm install 命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。
{
//1.项目基本信息
"name": "project3" ,
"version": "0.1.0",
"private": true,
//2.指定运行脚本命令
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
//4.生产环境所依赖模块的版本
"dependencies": {
"core-js": "^3.6.5" ,
"vue": "^2.6.11",
"vue-router": "^3.2.0"
},
//5.本地环境开发所依赖的版本
"devDependencies" : {
"@vue/cli-plugin-babel" : "~4.4.0",
"@vue/cli-plugin-router" : "~4.4.0",
"@vue/cli-service" : "~4.4.0",
"vue-template-compiler" : "^2.6.11"
}
// ,
// "vue":{ //配置项目启动端口号,项目启动时自动启动浏览器
// "devServer":{
// "port":"8888",
// "open":true
// }
// }
}
配置内容采用JSON格式,所有的内容都用双引号包裹
打开package.json,再最末端添加如下配置:
"vue":{
"devServer":{
"port":"8888",
"open":true
}
}
npm rum serve
module.exports = {
devServer:{
open:true
port:8889
}
}
组件化是Vue的精髓,Vue项目就是由一个一个的组件构成的。 我们主要的工作就是开发的组件.
<template>
<div>
测试页面...
div>
template>
<script>
//可以导入其组件
// import Header from '../components/header.vue'
//默认写法, 输出该组件
export default {
name:"Home", // 组件名称,用于以后路由跳转
data() {// 当前组件中需要使用的数据
return {}
},
methods: {}
}
script>
<style scoped>
/* 页面样式 加上scoped 表示样式就只在当前组件有效*/
style>
/*
项目运行时会加载 main为入口文件
html文件中,通过script src = 'xxx'标签引入js文件。
而vue中,通过 import 变量名 from 文件路径 的方式导入文件,不光可以导入js文件。
1.变量名: 指的是为导入的文件起一个名称,不是指导入的文件的名称,相当于变量名。
2.文件路径: 指的是文件的相对路径
*/
import Vue from 'vue'
import App from './App.vue' //主组件
import router from './router' //路由
//关闭启动提示
Vue.config.productionTip = false
//创建Vue实例
new Vue({
router, //为整个项目添加路由
render: h => h(App) //这是一个函数ES6语法,作用是生成模板: App = App.vue
}).$mount('#app') //挂载的是App.vue组件中的id为app的区域
1.App.vue 中的模板(HTML代码)
<template>
<div id="app"> 挂载的是这个div
<div id="nav">
这里是两个路由导航链接
1. to="/" 项目根路径 跳转的是首页
<router-link to="/">Homerouter-link> |
2. to="/about" 点击About按钮,跳转到about组件
<router-link to="/about">Aboutrouter-link>
div>
router-view 的作用是 根据访问的路径,渲染路径匹配到的视图组件
<router-view/>
div>
template>
// 引入所需文件
import Vue from 'vue' //vue库
import VueRouter from 'vue-router' //vue-router库
import Home from '../views/Home.vue' //首页
//使用路由功能
Vue.use(VueRouter)
//创建路由规则,元素就是一个一个的路由规则
const routes = [
{
path: '/',//路径
name: 'Home', //名称
component: Home //组件 Home.vue
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue' )
}
]
//创建路由管理器,管理routes
const router = new VueRouter({
routes
})
//export 用来导出模块 router就代表了整个路由文件
export default router
//视图部分
<template>
<div class="home">
//首页的logo
<img alt="Vue logo" src="../assets/logo.png" >
<HelloWorld msg="Welcome to Your Vue.js App"/>
div>
template>
JS部分
<script>
//导入了一个组件 HelloWorld.vue @符号表示 src这个目录
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
script>
HelloWorld.vue 组件页面
<template>
<div class="hello">
<h1>{{ msg }}h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation a>.
p>
<h3>Installed CLI Pluginsh3>
div>
template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
script>
<template>
<div class="header">{{msg}}div>
template>
<script>
//JS 部分
export default {
name:"Header", //组件的名称
data() { //data函数
return {
msg:"这是一个Header组件"
}
},
}
script>
//scoped 表示当前的样式,只作用与当前组件中的 template 视图. <style scoped>
.header {
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center; color: blue;
}
style>
修改Home.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png" >
<Header/>
div>
template>
<script>
// @ is an alias to /src
//import HelloWorld from '@/components/HelloWorld.vue' import Header from '@/components/Header.vue' ;
export default {
name: 'Home',
components: {
//HelloWorld
Header
}
}
script>
props : 是组件中的属性, 表示组件可以接受参数,
<template>
<div id="Header" class="header">{{msg}}div>
template>
<script>
export default {
name: "Header", //组件名称,用于路由的跳转
props:['msg']
};
script>
// scoped 表示当前style的样式只作用于当前组件的template代码中,其他地方不会被影响 <style scoped>
.header {
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center; color: blue;
}
style>
element-ui 是饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建
Element-UI官方站点:
https://element.eleme.cn/#/zh-CN
vue create el-project
npm i element-ui -S
//导入组件库
import ElementUI from 'element-ui'
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置Vue插件 将El安装到Vue上
Vue.use(ElementUI);
<template>
<div id="app">
<el-row>
<el-button>默认按钮el-button>
<el-button type="primary">主要按钮el-button>
<el-button type="success">成功按钮el-button>
<el-button type="info">信息按钮el-button>
<el-button type="warning">警告按钮el-button>
<el-button type="danger">危险按钮el-button>
el-row>
<div id="nav">
<router-link to="/">Homerouter-link> |
<router-link to="/about">Aboutrouter-link> div>
<router-view />
div>
template>
<template>
<div id="app">div>
template>
<style>
style>
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
routes
})
export default router
npm i axios
//引入axios
import axios from 'axios'
//Vue对象使用axios
Vue.prototype.axios = axios;
<el-dialog title="收货地址" :visible.sync ="dialogFormVisible" >
<el-form :model="form">
<el-form-item label="活动名称" :label-width ="formLabelWidth" >
<el-input v-model="form.name" autocomplete="off">
el-input>
el-form-item>
<el-form-item label="活动区域" :label-width ="formLabelWidth" >
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai">el-option>
<el-option label="区域二" value="beijing">el-option>
el-select>
el-form-item>
el-form>
<div slot="footer" class="dialog-footer" >
<el-button @click="dialogFormVisible = false">取 消el-button>
<el-button type="primary" @click="dialogFormVisible = false">确 定el- button>
div>
el-dialog>
<template>
<el-dialog title="登录" :visible.sync ="dialogFormVisible" >
<el-form>
<el-form-item label="用户名称" :label-width ="formLabelWidth" >
<el-input autocomplete="off">el-input>
el-form-item>
<el-form-item label="用户密码" :label-width ="formLabelWidth" >
<el-input autocomplete="off">el-input>
el-form-item>
el-form>
<div slot="footer" class="dialog-footer" >
<el-button type="primary" @click="dialogFormVisible = false">登录el- button>
div>
el-dialog>
template>
<script>
export default {
data() {
return {
formLabelWidth : "120px", //宽度
dialogFormVisible : true
};
}
};
script>
<style scoped>
style>
import Vue from "vue";
import VueRouter from "vue-router" ;
import Login from "@/components/Login.vue" Vue.use(VueRouter);
const routes = [
//访问 /,也跳转到login
{
path:'/',
redirect:'login' //重定向都login },
//登录
{
path:'/login',
name:'login',
component:Login
}
];
const router = new VueRouter({
routes,
});
export default router;
<template>
<div id="app">
<router-view>router-view>
div>
template>
<style>
style>
2.3.5 编写登录功能
<el-dialog title="登录" :show-close="false" :visible.sync="dialogFormVisible">
<el-button type="primary" @click="login">登录el-button>
data() {
return {
formLabelWidth : "120px", //宽度
dialogFormVisible : true, //是否关闭对话框
user: { username: "", password: "" }, //登录数据
};
},
使用 v-model, 将视图与模型进行绑定
<el-form>
<el-form-item label="用户名称" :label-width ="formLabelWidth" >
<el-input v-model="user.username" autocomplete="off">el-input>
el-form-item>
<el-form-item label="用户密码" :label-width ="formLabelWidth" >
<el-input v-model="user.password" autocomplete="off">el-input>
el-form-item>
el-form>
methods: {
login() {
//定义常量保存 url
const url = "http";
//发送请求
this.axios
.get(url, {
//携带参数
params: {
username: this.user.username,
password: this.user.password,
},
})
.then((res) => {
console.log();
//成功就将对话框关闭
this.dialogFormVisible = false;
})
.catch((error) => {
//出现错误使用ElementUI提供的消息提示
this.$message.error("对不起! 登录错误!");
});
},
},
postman模拟出一个server 步骤:
const url = "复制上面的地址/login";
在js中设置跳转,常用的一种方法是 this.$router.push,在vue基础中的编程式的导航:https://router.vuejs.org/zh/guide/essentials/navigation.html
methods: {
login() {
//定义常量保存 url
const url ="https://33284b33-e976-4124-a3a0-17044addc1e1.mock.pstmn.io/login" ; //发送请求
this.axios.get(url, {
//携带参数
params: {
username: this.user.username,
password: this.user.password,
},
}).then((res) => {
console.log(res.data);
alert("登录成功!");
//成功就将对话框关闭
this.dialogFormVisible = false;
//跳转页面,前端跳转页面必须使用路由,使用$router对象中的push方法
this.$router.push('/index');
})
.catch((error) => {
//出现错误使用ElementUI提供的消息提示
this.$message.error("对不起! 登录错误!");
});
},
},
<template>
<div>
<el-button type="danger">布局页面el-button> div>
template>
<script>
export default {
}
script>
<style scoped>
style>
router目录下 的index.js 路由文件
//导入布局组件
import Index from "@/components/Index.vue" //布局路由
{
path:'/index',
name:'index',
component: Index
}
];
Container 布局容器 ,是用于布局的容器组件,方便快速搭建页面的基本结构:
<el-container>
<el-header>Headerel-header>
<el-container>
<el-aside width="200px">Asideel-aside>
<el-main>Mainel-main>
el-container>
el-container>
<style scoped>
.el-container {
height: 720px;
}
.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: 30px;
}
style>
<template>
<div><el-container>
<el-header>后台管理el-header>
<el-container>
<el-aside width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
background-color ="#d3dce6"
>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location" >i>
<span>导航菜单span>
template>
<el-menu-item-group>
<el-menu-item index="1-1"
><i class="el-icon-menu">i>课程管理el-menu-item >
el-menu-item-group>
el-submenu>
el-menu>
el-aside>
<el-main>Mainel-main>
el-container>
el-container>
div>
template>
<script>
export default {};
script>
<style scoped>
.el-container {
height: 725px;
}
.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; }
style>
<template>
<el-button type="danger">课程信息el-button> template>
<script>
export default {};
script>
<style scoped>style>
//引入课程组件
import Course from "@/components/Course.vue"
//布局路由
{
path: "/index",
name: "index",
component: Index,
//添加子路由,使用 children属性 来表示子路由
children:[
//课程信息子路由
{
path:"/course",
name:"course",
component:Course
}
]
},
el-menu中 添加一个 router属性
<el-menu default-active="2" class="el-menu-vertical-demo" background- color="#d3dce6" router >
<el-menu-item-group>
<el-menu-item index="/course">
<i class="el-icon-menu">i>课程管理 el-menu-item>
el-menu-item-group>
<el-main>
<router-view>router-view>
el-main>
我们通过table组件来实现一个课程页面展示的功能,通过查看Element-UI库,我们需要Table 表 格.
进入Element-UI官方,找到Table组件,拷贝源代码到vue页面中,如下
复制表格组件相关的代码到 Course.vue中
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> el-table-column>
<el-table-column prop="name" label="姓名" width="180"> el-table-column>
<el-table-column prop="address" label="地址"> el-table-column>
el-table>
template>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02" ,
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄"
},
{
date: "2016-05-04" ,
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄"
},
{
date: "2016-05-01" ,
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄"
},
{
date: "2016-05-03" ,
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄"
}
]
};
}
};
script>
我们查看一下,ElementUI 的表格的代码,分析一下表格数据是如何显示的
//视图部分 进行页面展示
<template>
//el-table组件 绑定了tableData数据
<el-table :data="tableData" style="width: 100%">
//el-table-column
表示表格的每列,prop属性与模型数据中的key对应 ,label 列名
<el-table-column prop="date" label="日期" width="180">el-table-column> <el-table-column prop="name" label="姓名" width="180">el-table-column> <el-table-column prop="address" label="地址">el-table-column>
el-table>
template>
<script>
//export default 相当于提供一个接口给外界,让其他文件通过 import 来引入使用。 export default {
//data() 函数
data() {
return {
//数据部分
tableData: [
{
date: "2016-05-02" ,
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄"
}
};
}
};
script>
<template>
<div class="table">
<el-table
style="width: 100%"
border
height="550"
:data="courseList"
v-loading="loading"
element-loading-text ="数据加载中..."
>
<el-table-column fixed="left" prop="id" label="ID">el-table-column>
<el-table-column prop="course_name" label="课程名称">el-table-column>
<el-table-column prop="price" label="价格">el-table-column>
<el-table-column prop="sort_num" label="排序">el-table-column>
<el-table-column prop="status" label="状态">el-table-column>
el-table>
div>
<script>
export default {
name: "Course",
title: "课程管理",
//数据部分
data() {
return {
//定义数据
loading: false, //是否弹出加载提示
courseList: [], //定义集合,保存从接口获取的参数
};
},
//钩子函数,在DOM页面生成之前执行
created() {
//在页面生成之前, 调用loadCourse
this.loadCourse();
},
//方法集合
methods: {
//方法1: 获取课程信息
loadCourse() {
//开启
this.loading = true;
//访问后台接口,获取数据并返回
return this.axios
.get(
"http://localhost:8080/lagou_edu_home/course? methodName=findCourseList")
.then((res) => {
console.log(res.data);
//将获取到的数据赋值给 courseList
this.courseList = res.data;
this.loading = false;
});
},
},
};
script>
当我们在前端项目中,向后端发送请求的获取课程数据的时候,出现了跨域问题:
Access to XMLHttpRequest at 'http://localhost:8080/lagou_edu_home/course? methodName=findCourseList' from
origin 'http://localhost:8088' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
跨域是指通过JS在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,只要协
议、域名、端口有任何一个不同,都被当作是不同的域,浏览器就不允许跨域请求
跨域的允许主要由服务器端控制。服务器端通过在响应的 header 中设置 Access-Control-Allow- Origin 及相关一系列参数,提供跨域访问的允许策略
<dependency>
<groupId>com.thetransactioncompanygroupId>
<artifactId> cors-filterartifactId>
<version>2.5version>
dependency>
<filter>
<filter-name>corsFilterfilter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter filter-class>
filter>
<filter-mapping>
<filter-name>corsFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
解决跨域问题之后,页面显示数据
<el-input
placeholder="请输入内容"
v-model="input4">
<i slot="prefix" class="el-input__icon el-icon-search" >i>
el-input>
Course.vue 添加输入框
<template>
<div>
<el-input placeholder="请输入课程名称">
<i slot="prefix" class="el-input__icon el-icon-search" >i> el-input>
div>
template>
通过基础的 24 分栏,迅速简便地创建布局。
通过 row 和 col 组件,并通过 col 组件的 span 属性我们就可以自由地组合布局。
<el-row :gutter="20">
<el-col :span="6"><div class="grid-content bg-purple">div>el-col>
<el-col :span="6"><div class="grid-content bg-purple">div>el-col>
<el-col :span="6"><div class="grid-content bg-purple">div>el-col>
<el-col :span="6"><div class="grid-content bg-purple">div>el-col>
el-row>
<el-row :gutter="10">
<el-col :span="5">
<el-input clearable placeholder="课程名称">
<i slot="prefix" class="el-input__icon el-icon-search" >i>
el-input>
el-col>
el-row>
<el-row :gutter="10">
<el-col :span="5">
<el-input clearable placeholder="课程名称">
<i slot="prefix" class="el-input__icon el-icon-search" >i> el-input>
el-col>
<el-col :span="1">
<el-button type="primary">查询el-button>
el-col>
el-row>
双向数据绑定
Model 模型
//数据部分
data() {
//定义查询条件
return {
loading: false, //是否弹出加载提示
courseList: [], //定义集合,保存从接口获取的参数
filter: { course_name : "" } //查询条件
};
},
View 视图
<el-input v-model="filter.course_name" clearable placeholder="课程名称">
<i slot="prefix" class="el-input__icon el-icon-search" >i>
el-input>
设置点击事件
<el-button type="primary" @click="search">查询el-button>
methods中添加方法
search() {
//开启加载提示
this.loading = true;
//发送请求
return this.axios
.get("http://localhost:8080/lagou_edu_home/course" , { //携带参数
params: {
methodName: "findByCourseNameAndStatus" ,
course_name: this.filter.course_name
}
})
.then(res => {
console.log(res);
this.courseList = res.data;
//关闭加载
this.loading = false;
})
.catch(error => {
this.$message.error("获取数据失败!");
});
}