Vue框架教程-从入门到项目实战
Posted 杨星辰Red
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue框架教程-从入门到项目实战相关的知识,希望对你有一定的参考价值。
创建Vue项目
我们通过vue-cli创建一个vue项目,
- 在cmd窗口输入 vue ui 进入vue-cli可视化界面(如果无效请升级vue-cli版本)
- 点击创建,选择一个项目目录
- 输入项目名称和git初始化窗口(可选)
- 选择预设,可以选择手动和预定的设置 (预设就是一套定义好的插件和配置。 你也可以将自己的配置保存成预设,方便以后创建项目使用。)
- 选择项目功能(也可以在创建后手动添加)
- 选择配置
- 等待创建完项目即可(如果是第一次可能有点慢)
- 启动项目
引入Element-Ui
- 点击左侧插件,点击右上角添加插件
- 点击所有插件,输入element,选中第一个,点击创建
- 配置插件,点击手工按需导入,选中zh-cn中文,完成按照即可
手动引入组件
或者导入一行
Git上传仓库
我们的代码一般都会上传到Gitee或者GitHub中的远程仓库托管,这样我们电脑项目丢失或者需要旧版本的项目可以直接将远程的代码下载(拉取)到本地进行开发。
- 我们先安装Git软件 https://git-scm.com/
- 前往Gitee注册账号https://gitee.com/
- 配置SSH公钥,点击怎么生成公钥然后按照步骤进行申请
-
在CMD窗口输入上方黄色指令进行生成,其中的”xxx“改成注册的邮箱
-
如果cmd窗口生成失败,进入桌面鼠标右键点击Git GUl Here
-
点击show ssh key,将生成key的指令粘贴进去弹出账号密码输入gitee注册的账号密码即可生成完成
-
生成完成后第三步的公钥取和输入自定义标题即可完成添加公钥
-
新建仓库
-
输入仓库名称选择开源或者私有即可,点击创建
-
将创建的vue项目上传到刚刚创建的仓库中,我们初始化一下Git(一定要执行)
-
我们cd 进入vue项目的更目录查询一下项目是否干净
-
我们将当前下的文件提交到本地的git中,
-
然后我们在执行一个 git status,显示当前分支和目录处于干净状态
- 我们将本地的git上传到远程gitee仓库,先复制黄色内容,在刚刚的cmd中执行一下,表示上传成功
- 最后我们刷新一个我们的仓库,就可以看见我们项目了
创建新的分支
我们在添加新功能的时候会创建一个分支
git checkout -b login
PS D:\\heima_shop\\xcwl_shop> git checkout -b login
Switched to a new branch 'login'
PS D:\\heima_shop\\xcwl_shop>
查看所有分支
git branch
vscode从远程仓库拉代码
1,在你写项目的磁盘里新建文件夹
2,登录Gitee
3,复制克隆/下载处的地址
4,打开VScode,在新建的文件夹下,打开终端
5,运行 git clone + 地址 ,回车,项目就拉取下来了
提交代码
将本地代码提交到Git仓库
- 获取当前文件(跟仓库代码做对比,那些修改过,那些是新增的)
- git add . 将代码全部添加在暂存区
- git commit -m “完成了登录功能” 将代码提交到本地git仓库
- 合并分支,获取当前分支:git branch,切换到主分支git checkout master
- 当前在主分支输入命令git merge login 将login分支合并到当前主分支
- 当前login分支的代码已经全部合并到主分支了,我们将主分支代码同步到gitee仓库通过 git push命令
- 在gitee仓库创建一个子分支,git push -u origin login,创建了一个login子分支
Vue
axios
注意:要先下载引入axios组件
在main.js中引入,即可全局使用
本地存储Token
//1.将登录成功之后的Token存放到客户端的sessionStorage中,为什么不存放到localstorage中呢,因为他是持久性机制,sessionstorage是会话机制
//1.1项目中除了登录之外的其他API接口,必须在登录之后才能访问
//1.2token只能在当前网站打开期间生效,所以将token存放在sessionstorage中
window.sessionStorage.setItem("token", req.data.data);
//2.通过编程式导航跳转到后台首页,路由地址是/home
this.$router.push("/home");
路由导航守卫
//路由守卫,在执行路由前执行本方法来做认证操作
// to:要去的路径,from:获取从那个页面路径跳转而来的,next:放行
router.beforeEach((to,from,next)=>
// 判断当前路径是否为login ,如果是true 着放行
if(to.path==="/login") return next();
//获取当前token
const token=window.sessionStorage.getItem("token");
//如果当前token为空,着返回到login页面
if(!token)return next("/login");
//如果上面全部都过了,那么执行放行
next();
)
配置请求token
我们在除了登录和注册接口中不需要携带token,但是其他所有的请求中必须要携带token来确保当前账户,
如果我们每个axios中手动在head中添加会很麻烦,所以我们定义一个全局的拦截器
在每次请求的方法中,会先调用我们定义的全局拦截器,在继续执行我们的请求接口
//通过调用axios中的interceptors属性中的request成员(请求拦截器)中的use函数来添加全局请求头
axios.interceptors.request.use(config =>
//通过返回的config对象中的headers属性添加一个Authorization=本地存储的token
config.headers.Authorization=window.sessionStorage.getItem("token")
//在最后必须teturn config
return config
)
作用域插槽
可以定义一个插槽,切插槽可以获取当前对象
<el-table-column label="状态">
<!-- 我们创建一个作用域插槽模板来写一个开关按钮 通过slot-scope="scope"来接收当前一行对象数据-->
<template slot-scope="scope">
<!-- 可以通过scope.row获取当前一行对象,通过.对象中的参数可以获取对应的值 -->
scope.row.mg_state
<!-- 定义一个开关按钮,v-mode的值为true,false,对应开还是关 -->
<el-switch v-model="scope.row.mg_state"> </el-switch>
</template>
</el-table-column>
字符串 数组转换
数组转字符串用.join()方法不填参数表示转换已,分割 a,b,c 填参数 .join(“.”) 打印 a.b.c
Css
在创建vue项目中,页面样式默认都是有margin和padding所以我们创建一个全局css样式表来设置全部页面的默认样式
在assets下创建css文件在创建一个global.css文件
/* 全局css样式 */
html,body,#app
height: 100%;
margin: 0px;
padding: 0px;
flex布局
/*设置布局方式为flex*/
display: flex;
/*设置靠右对齐*/
justify-content: space-between;
/*设置上下居中*/
align-items: center;
class绑定多css
:class="['borderbottom','vcenter']"
class做判断
功能实现
退出功能
退出功能原理详解
基于token的方式实现退出比较简单,只需要将本地存储的token销毁掉,这样后续的请求就不会携带token并且路由守卫也获取不到存储的token就会被拦截强制跳转到login登录页面,必须重新登录才可以获取新的token存储到本地就可以访问其他页面
<template>
<div>
<el-button type="info" @click="tuichu">退出</el-button>
</div>
</template>
<script>
export default
methods:
tuichu()
//获取本地的sessionStorage执行remove方法清除token
window.sessionStorage.removeItem("token");
//通过路由puth跳转(重定向)到login登录界面
this.$router.push("/login");
</script>
<style scoped>
</style>
首页布局
Head头部
<template>
<!-- 创建布局容器 -->
<el-container class="home-container">
<!-- 头部 -->
<el-header>
<div class="header-div">
<img
src="../assets/logo.png"
alt=""
style="height: 50px; width: 50px"
/>
<!-- 设置跟图片间隔15px -->
<span style="margin-left: 15px">电商后台管理系统</span>
</div>
<el-button type="info" @click="tuichu">退出</el-button>
</el-header>
<!-- 内容主体区域 -->
<el-container>
<!-- 内容主体左侧侧边栏 -->
<el-aside width="200px">Aside</el-aside>
<!-- 内容主体右侧内容 -->
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
<script>
export default
methods:
tuichu()
// 获取本地的sessionStorage执行remove方法清除token
window.sessionStorage.removeItem("token")
// 通过路由puth跳转到login登录界面
this.$router.push("/login")
,
,
</script>
<style scoped>
/* 给容器设置宽高 */
.home-container
height: 100%;
width: 100%;
.el-header
background-color: #373d41;
/* 设置flex布局方式 */
display: flex;
/* 靠右对齐 */
justify-content: space-between;
padding-left: 0;
/* 设置上下居中 */
align-items: center;
color: #fff;
font-size: 20px;
.header-div
/* 设置flex布局方式 */
display: flex;
/* 设置居中对其 */
align-items: center;
.el-aside
background-color: #333744;
.el-main
background-color: #eaedf1;
</style>
左侧侧边栏
<el-aside width="200px">
<!-- 侧边栏内容区域 -->
<el-menu
background-color="rgb(51,55,68)"
text-color="#fff"
active-text-color="#ffd04b"
>
<!-- 一级菜单 -->
<el-submenu index="1">
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 菜单图标 -->
<i class="el-icon-location"></i>
<!-- 采单文本 -->
<span>导航一</span>
</template>
<!-- 二级菜单 -->
<el-menu-item index="1-4-1">
<!-- 二级菜单模板区域 -->
<template slot="title">
<!-- 菜单图标 -->
<i class="el-icon-location"></i>
<!-- 菜单文本 -->
<span>导航一</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
获取侧边栏数据,并且渲染到页面
<template>
<!-- 创建布局容器 -->
<el-container class="home-container">
<!-- 头部 -->
<el-header>
<div class="header-div">
<img
src="../assets/logo.png"
alt=""
style="height: 50px; width: 50px"
/>
<!-- 设置跟图片间隔15px -->
<span style="margin-left: 15px">电商后台管理系统</span>
</div>
<el-button type="info" @click="tuichu">退出</el-button>
</el-header>
<!-- 内容主体区域 -->
<el-container>
<!-- 内容主体左侧侧边栏 -->
<el-aside width="200px">
<!-- 侧边栏内容区域 -->
<el-menu
background-color="rgb(51,55,68)"
text-color="#fff"
active-text-color="#ffd04b"
>
<!-- 一级菜单 -->
<el-submenu :index="''+item.id" v-for="(item, index) in meaunList" :key="index">
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 菜单图标 -->
<i class="el-icon-location"></i>
<!-- 采单文本 -->
<span>item.authName</span>
</template>
<!-- 二级菜单 -->
<el-menu-item :index="''+item.children[0].id">
<!-- 二级菜单模板区域 -->
<template slot="title">
<!-- 菜单图标 -->
<i class="el-icon-location"></i>
<!-- 菜单文本 -->
<span>item.children[0].authName</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 内容主体右侧内容 -->
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
<script>
export default
data()
return
meaunList: [],
,
// created:生命周期函数,在进入页面时先加载这个函数在加载html....
// created跟mounted有什么区别呢? created加载完在加载html,mounted是html加载完在执行mounted,所以created的执行优先级比mounted高
//this.getMenuList()来获取axios返回的菜单数据
created()
this.getMenuList()
,
methods:
tuichu()
// 获取本地的sessionStorage执行remove方法清除token
window.sessionStorage.removeItem("token")
// 通过路由puth跳转到login登录界面
this.$router.push("/login")
,
//获取所有的菜单
async getMenuList()
//变量名data:req这样写可以直接获取请求对象中的data属性 ,变量名称为req
const data: req = await this.$http.get("/menus")
// console.log(req);
// const data = await this.$http.get("/menus")
// 判断是否获取成功,如果失败返回失败信息
if (req.meta.status !== 200) return this.$message.error(req.meta.msg)
//成功后将菜单信息定义到data数组
this.meaunList = req.data
,
,
</script>
<style scoped>
/* 给容器设置宽高 */
.home-container
height: 100%;
width: 100%;
.el-header
background-color: #373d41;
/* 设置flex布局方式 */
display: flex;
/* 靠右对齐 */
justify-content: space-between;
padding-left: 0;
/* 设置上下居中 */
align-items: center;
color: #fff;
font-size: 20px;
.header-div
/* 设置flex布局方式 */
display: flex;
/* 设置居中对其 */
align-items: center;
.el-aside
background-color: #333744;
.el-main
background-color: #eaedf1;
</style>
侧边栏美化
.el-submenu
/* 给菜单图标设置间距 */
margin-right: 10px;
.el-menu
/* 将侧边栏默认的边框去掉 */
border-right: none;
给手动设置图标icon
侧边栏伸缩
侧边栏点击收缩,点击展开,其实就是定义一个点击事件然后修改侧边栏的collapse属性为true或者false
<!-- 定义展开伸缩点击事件 -->
<div class="toggle-button" @click="toggleCollapse">|||</div>
<el-menu
background-color="rgb(51,55,68)"
text-color="#fff"
active-text-color="#409eff"
<!-- 是否只保持一个子菜单的展开 -->
unique-opened
<!-- 是否水平折叠收起菜单 这里调用的是toggleCollapse方法,如果方法里面有本方法会优先调用方法其次在调用data中的-->
:collapse="iscollapse"
<!-- 是否开启折叠动画 这里调用的是data中的transition-->
:collapse-transition="transition"
>
</el-menu>
data()
return
// 是否折叠
iscollapse:false,
//是否开启折叠动画
transition:false
// 点击按钮,切换菜单显示和展开
toggleCollapse()
this.iscollapse=!this.iscollapse
,
实现路由重定向
我们在登录login成功后跳转到我们home页面,会默认加载welcome页面(这里使用重定向)
我们先将welcome页面注册到home子路由中
path: "/Home",
name: "Home",
component: () => import("../components/Home.vue"),
// 默认页面时重定向/welcome子路由页面
redirect: "/welcome",
//注册子路由,主路由页面中可以随时切换到子路由页面,切换到那个区域由router-view标签决定
children: [
path: "/welcome",
name: "welcome",
component: () => import("../components/Welcome.vue"),
,
],
,
将子路由页面加载到home主路由那个区域?在主路由用router-view来决定
<!-- 内容主体右侧内容 -->
<el-main>
<!--定义到这里-->
<router-view></router-view>
</el-main>
导航栏小bug
我们点击二级菜单后虽然有高亮,但是刷新后就没有高亮了,
我们可以通过default-active=“二级菜单路径” 来定义高亮
解决方法:
我们在点击二级菜单时将path路径保存进sessionstora中,在将存放在sessiostora中的path路径赋值给default-active即可
<el-menu
//设置二级菜单高亮
//这里的active对应的时data中的active
:default-active="active"
>
<!-- 二级菜单 -->
<el-menu-item
v-for="(item, index) in item.children"
:index="'/' + item.path"
:key="index"
//定义一个点击方法将path传递过去
@click="setactive('/' + item.path)"
>
data()
return
// 获取本地存储的上次点击的菜单栏
active:window.sessionStorage.getItem("active"),
//点击后执行本方法,将path存放进sessionstora中
setactive(active)
window.sessionStorage.setItem("active", active)
,
用户列表
因为每个页面都有面包屑导航栏,而且还跟卡片面板挨得太近,在全局css样式中添加样式
/* 面包屑 */
.el-breadcrumb
margin-bottom: 15px;
font-size: 12px;
/* 卡片面板 */
.el-card
/* 设置卡片阴影 */
box-shadow: 0,1px,1px rgb(0, 0,0, 0.15);
面包屑
<!-- 面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<!--点击即可回到home首页-->
<el-breadcrumb-item :to=" path: '/Home' ">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
<el-breadcrumb-item>用户列表</el-breadcrumb-item>
</el-breadcrumb>
卡片面板
<!-- 卡片试图区 -->
<el-card class="box-card">
<!-- 设置两栏间距 -->
<el-row :gutter="20">
<!-- 设置这一栏大小 -->
<el-col :span="8">
<!-- 搜索与添加区域 -->
<el-input placeholder="请输入内容">
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<!-- 按钮 -->
<el-button type="primary">添加用户</el-button>
</el-col>
</el-row>
</el-card>
用户数据展示
- 获取所有用户数据
<script>
export default
data()
return
//存放用户数据的数组
userList:[],
//存放用户总数的数据
usertotal:'',
//请求用户数据传递的参数
queryInfo:
query:'',
pagenum:'1',
pagesize:'10'
,
created()
//第一时间调用获取用户数据
this.getUserList()
,
methods:
//通过axios获取用户数据
async getUserList()
// get 传递参数params:参数对象a:1,b:2
const data:req = await this.$http.get("/users",params:this.queryInfo)
// console.log(userList)
if(req.meta.status!==200)return this.$message.error("获取用户数据失败!")
// 将用户数组存放进data中的userList数组
this.userList=req.data.users
// 将用户总数存放usertotal
this.usertotal=req.data.total
// console.log(this.userList)
,
,
</script>
#### 用户数据渲染
<!-- 用户数据表格 -->
<el-table :data="userList" border stripe>
<!-- :data表示获取用户数组 border纵向边框 stripe斑马纹 table -->
<!-- el-table-column每一模板列数据 label列头部标题 prop列内容数据 -->
<el-table-column label="用户名" prop="username"></el-table-column>
<el-table-column label="邮箱" prop="email"></el-table-column>
<el-table-column label="电话" prop="mobile"></el-table-column>
<el-table-column label="角色" prop="role_name"></el-table-column>
<el-table-column label="状态" prop="mg_state"></el-table-column>
<el-table-column label="操作"></el-table-column>
</el-table>
表格跟搜索框挨在一起不好看,在全局样式中设置table表格跟头部搜索框一段距离,并且表格字体太大修改小一点
/* tbale表格样式 */
.el-table
/* 设置表格top外边距15px */
margin-top: 15px;
/* 设置表格内容字体大小 */
font-size: 13px;
编写表格状态列
我们在状态这一列定义一个作用域插槽
<el-table-column label="状态" prop="mg_state">
<!-- 我们创建一个作用域插槽模板来写一个开关按钮,通过slot-scope="scope"来接收当前一行对象数据 -->
<template slot-scope="scope">
<!-- 可以通过scope.row获取当前一行对象,通过.对象中的参数可以获取对应的值 -->
scope.row.mg_state
<!-- 定义一个开关按钮,v-mode的值为true,false,对应开还是关 -->
<el-switch v-model="scope.row.mg_state"></el-switch>
</template>
</el-table-column>
编写操作列
操作列定义了三个按钮,编辑,清除,分配角色,这里我们依然使用作用域插槽
<!-- 为了保持按钮在浏览器不同大小窗口都排列成一行不变形 我们给这行添加一个固定宽度 -->
<el-table-column label="操作" width="180px">
<template slot-scope="values">
<!-- 修改按钮 type表示按钮颜色,icon表示按钮图标,size表示按钮大小-->
<el-button type="primary" icon="el-icon-edit" size="mini"></el-button>
<!-- 清除按钮 -->
<el-button type="danger" icon="el-icon-delete" size="mini"></el-button>
<!-- 分配角色按钮 -->
<el-button type="warning" icon="el-icon-setting" size="mini"></el-button>
</template>
</el-table-column>
我们实现一下鼠标移到按钮上显示按钮功能提示
我们可以给按钮外侧套一层Tooltip 文字提示
<!-- 分配角色按钮 effect表示主体,content提示文字,placement提示方向-->
<el-tooltip effect="dark" content="分配角色" placement="top">
<el-button type="warning" icon="el-icon-setting" size="mini"></el-button>
</el-tooltip>
数据分页
当我们数据足够多的时候,我们需要设置分页查看
先添加Pagination 分页组件
<!-- 分页区域 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.pagenum"
:page-sizes="[1, 2, 3, 50]"
:page-size="queryInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="usertotal"
>
<!-- @size-change="handleSizeChange" 表示切换了每页条数的菜单会触发handleSizeChange方法函数 ,在这个函数中可以拿到最新的每页条数-->
<!-- @current-change="handleCurrentChange" 页码值发生了切换会触发handleCurrentChange方法函数 -->
<!-- :current-page="currentPage4" 当前显示的是第几页数据 -->
<!-- :page-sizes="[100, 200, 300, 400]" 下拉菜单显示可以切换显示多少条数据 -->
<!-- :page-size="100" 当前每页显示多少条数据-->
<!-- layout 组件布局显示那些功能,比如每页显示多少条数据的下拉菜单 -->
<!-- :total="400" 数据总数 -->
</el-pagination>
<script>
export default
data()
return
//存放用户数据的数组
userList: [],
//存放用户总数的数据
usertotal: "",
//请求用户数据传递的参数
queryInfo:
query: "",
// 当前页数
pagenum: 1,
// 显示多少条数据
pagesize: 10,
,
,
created()
//第一时间调用获取用户数据
this.getUserList()
,
methods:
//通过axios获取用户数据
async getUserList()
// get 传递参数params:参数对象a:1,b:2
const data: req = await this.$http.get("/users",
params: this.queryInfo,
)
// console.log(userList)
if (req.meta.status !== 200)
return this.$message.error("获取用户数据失败!")
// 将用户数组存放进data中的userList数组
this.userList = req.data.users
// 将用户总数存放usertotal
this.usertotal = req.data.total
// console.log(this.userList)
,
//当页面切换显示多少条数据时会触发并接收选择的多少条数据
handleSizeChange(newSize)
//用户切换每页显示多少条数据,我们修改data中的属性
this.queryInfo.pagesize=newSize
//设置完每页显示多少条数据后,重新获取一次每页显示多少条的数据
this.getUserList()
,
// 当页码值发生了切换会触发并接收切换的页面值
handleCurrentChange(newPage)
//设置当前页面
this.queryInfo.pagenum=newPage
//设置完当前页码后重新获取当前设置完的页面的数据
this.getUserList()
,
</script>
我们的分页组件需要跟表格设置点距离
在全局样式中添加
/* 分页样式 */
.el-pagination
margin-top: 15px;
用户状态修改
我们点击Switch开关按钮发送一条请求修改用户的状态
@change="userStateChanged(values.row)" 代表开关点击后,会触发userStateChanged方法并且携带当前对象
<el-switch v-model="values.row.mg_state" @change="userStateChanged(values.row)"> </el-switch>
//状态按钮点击后执行这个函数方法,来修改用户状态函数
async userStateChanged(user_Row)
//put请求
const data:req=await this.$http.put("/users/"+user_Row.id+"/state/"+user_Row.mg_state)
// 如果修改失败
if(req.meta.status!==200)
// 当我们点击按钮后会直接在本地改成false/true,但是数据库没有修改成功,我们将本地的修改为原来的boolen
user_Row.mg_state=!user_Row.mg_state
// 发送提示信息
return this.$message.error("修改用户状态失败!")
// 如果修改成功,我们发送提示信息
this.$message.success("更新用户状态成功!")
搜索用户
我们给input绑定一个v-model属性值为data中的queryInfo.query,在再buttom上添加一个点击事件,我们点击后调用getuserlist方法即可?
为什么我们不重新写个获取用户的请求而是重复用一个请求呢?
我们的获取用户请求中有三个参数,第一个参数是用户名(可以为空,我们为空代表获取所有用户,不为空代表查询当前输入的用户名)
所有我们可以复用getuserlist方法
<el-input placeholder="请输入内容" v-model="queryInfo.query">
<el-button slot="append" icon="el-icon-search" @click="getUserList" ></el-button>
</el-input>
如果这个时候用户想查询全部用户信息了,又要吧输入框的信息全部清除再次点击一次查询,反而很麻烦
<!--我们给input加一个 clearable 属性代表 输入框可以显示清空按钮,@clear="getUserList"表示 当我们点击清空按钮后执行一个函数
我们清空后会默认执行一个getUserList函数,这个时候我们的v-model="queryInfo.query"的值为空,我们请求getUserList的时候就会显示全部用户信息了-->
<el-input placeholder="请输入内容" v-model="queryInfo.query" clearable @clear="getUserList">
<el-button slot="append" icon="el-icon-search" @click="getUserList" ></el-button>
</el-input>
添加用户
点击添加按钮弹出添加框
<!-- 添加用户对话框 -->
<el-dialog
title="提示"
:visible.sync="addUservisiblesync"
width="50%">
<!--弹窗主体区域-->
<span>这是一段信息</span>
<!--底部按钮组件-->
<span slot="footer" class="dialog-footer">
<!--点击取消将addUservisiblesync修改为false 这样弹窗就会消失-->
<el-button @click="addUservisiblesync = false">取 消</el-button>
<el-button type="primary" @click="addUservisiblesync = false">确 定</el-button>
</span>
</el-dialog>
<!--
title:弹窗标题
:visible.sync:表示是否显示
width:弹窗大小
-->
给弹出框添加表单
<!--弹窗主体区域-->
<el-form
:model="addUserForm"
:rules="addUserFormrules"
ref="ruleAddUserForm"
label-width="70px"
>
<!-- :model绑定表单对象,rules校验规则, -->
<!--label表示input左侧文字 ,prop表示校验规则名称-->
<el-form-item label="用户名" prop="username">
<!--v-model表示与addUserForm对象下的属性绑定-->
<el-input v-model="addUserForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addUserForm.password"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="addUserForm.email"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input v-model="addUserForm.mobile"></el-input>
</el-form-item>
</el-form>
// 添加用户form表单对象
addUserForm:
username
1、下载与安装Vue.js
Vue.js的官网: https://cn.vuejs.org/
如果在项目中使用Vue.js框架,有两种方式:一是在页面中使用Script的方式直接引入,可以在官网下载Vue.js的源码,也可以使用CDN的方式引入;二是使用NPM的方式构建Vue项目,或者是使用Vue-cli脚手架创建项目。
本节我们先通过Script标签在网页引入Vue.js的方式来学习Vue实例,因为这种方法上手简单,适合初学者学习Vue的基础语法入门。在后面的教程中,会单独介绍使用NPM和Vue-cli的方式搭建Vue项目。
本地引入
我们可以访问Vue.js的官网下载,地址:https://vuejs.org/js/vue.min.js
也可以通过访问GitHub下载,地址:https://github.com/vuejs/vue
在HTML页面中使用script标签引入:
<script src="js/vue.js"></script>
使用CDN引入
国内常用的CDN公共库有:
腾讯网静态资源公共库: https://libs.qq.com/
字节跳动静态资源公共库: http://cdn.bytedance.com/
BootCDN服务: https://www.bootcdn.cn/
又拍云JS库CDN服务: https://upcdn.b0.upaiyun.com/
我们以BootCDN为例,打开BootCDN网站,搜索Vue:
在搜索结果列表中选择Vue,进入Vue的CDN库列表,选择对应的版本,点击复制链接,或者是复制 <script>
标签,将Vue库引入到网页中:
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.common.js"></script>
2、创建第一个Vue实例
声明式渲染
Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM中。
HTML代码:
<div id="app">
{{ message }}
</div>
JS代码:
var app = new Vue({
el: \'#app\',
data: {
message: \'Hello Vue!\'
}
})
完整示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue实例</title>
</head>
<body>
<div id="app">
{{ message }}
</div>
<script src="js/vue.min.js"></script>
<script>
var app = new Vue({
el: \'#app\',
data: {
message: "Hello Vue"
}
})
</script>
</body>
</html>
输出结果:
Hello Vue
通过上面的代码,我们已经成功的创建了第一个Vue应用。上面代码中JS的数据和DOM已经建立了关联,所有的东西都是响应式的。怎么确认数据是响应式的呢?我们可以打开浏览器,按F12进入开发者控制台(Console),修改 app.message
的值,可以看到页面中的数据也做了响应的更新,效果如下图:
每个Vue应用都是通过用 Vue()
函数创建一个新的Vue实例开始的:
var vm = new Vue({
// 选项
})
虽然没有完全遵循MVVM模型,但是Vue的设计也受到了它的启发,因此在文档中经常会使用 vm
(ViewModel的缩写)这个变量名表示Vue实例。