目录
1.简介
vue是一套用于构建用户界面的渐进式的js框架
Vue的核心库只关注视图层,
MVVM模式的实现者——双向数据绑定模式.
Model:模型层,在这里表示JavaScript对象
View:视图层,在这里表示DOM (HTML操作的元素)
ViewModel:连接视图和数据的中间件,Vue.js 就是MVVM中的ViewModel层的实现者
在MVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义一个Observer观察者
ViewModel能够观察到数据的变化,并对视图对应的内容进行更新
ViewModel能够监听到视图的变化,并能够通知数据发生改变
核心就是实现了DOM监听与数据绑定
2.基础语法
2.1.快速入门
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="app">
<!--插值表达式获得属性-->
<h1>{{msg}}</h1>
<!--插值表达式调用方法-->
{{sayHi()}}
</div>
</body>
<script>
new Vue({
el: '#app',//绑定元素
data: {//放数据的,里面存放键值对
msg: "Hello Vue"//以后数据通过ajax请求来获得
},
methods: {//方法
sayHi: function () {
alert("Hello")
}
}
})
</script>
</html>
2.2.常用标签
v-model
<body>
<div id="app">
<!--将标签的value值和vue实例中的data属性进行绑定,双向绑定-->
请输入你的年龄:<input type="text" v-model="age"/><br>
-------<br>
我今年{{age}}岁
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
age: "19"
}
})
</script>
v-on
<body>
<div id="app">
<!--通过配合具体事件名,绑定vue种定义的函数-->
<!--v-on:可以简写成@-->
<input type="text" v-on:input="change"/><br>
<input type="text" @input="change2"/><br>
<button v-on:click="click">点击</button>
</div>
</body>
<script>
new Vue({
el: '#app',
methods: {
change: function () {
console.log("正在输入")
},
change2: function (event) {
//在响应函数中,可以使用内置对象event,该对象表示当前事件
//event.target.value:获得当前事件的value值
console.log(event.target.value)
},
click: function () {
console.log("点击了")
}
}
})
</script>
v-bind
<body>
<div id="app">
<!--插值表达式能作为属性值的部分,可以使用v-bind进行属性绑定,可以简写为:-->
<!--错误的语法<a href="{{link}}">百度</a>-->
<a v-bind:href="link">百度</a>
<a :href="link">百度</a><!--简写-->
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
link: "http://www.baidu.com"
}
})
</script>
v-html和v-text
<body>
<div id="app">
<!--v-html-->
<span v-html="link"></span><!--span标签里面就会放一个超链接-->
<!--v-text-->
<span v-text="link"></span><!--span标签里面只会以文本的形式展示-->
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
link: "<a href='http://www.baidu.com'>百度</a>"
}
})
</script>
v-if
<body>
<div id="app">
<button @click="temp=!temp">点我</button>
<p v-if="temp">嘟嘟</p><!--当temp为true显示-->
<p v-else-if="temp2">呜呜</p><!--当temp为false,temp2为true显示-->
<p v-else>啦啦</p><!--当temp为false,temp2为false显示-->
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
temp: false,
temp2: true
}
})
</script>
v-show
用法和v-if相同,v-show="true"时显示内容但是v-show改变的是元素的样式display为none,v-if是直接新增和删除元素v-show效率更高
template
<body>
<template v-if="true"><!--可以配合v-if控制多个标签的显示,但是不能和v-show使用,因为template本来就不可见,不能设置display-->
<!--里面第一个有且仅有一个div-->
<div>
<p>1</p>
<p>2</p>
<p>3</p>
</div>
</template>
</body>
v-for
<body>
<div id="app">
<li v-for="a in args">{{a}}</li>
<hr/><!--含下标-->
<li v-for="(a,i) in args" :key="i">{{i}}-{{a}}</li>
<hr/><!--遍历对象属性,第一个是值,第二个是键-->
<li v-for="(v,k) in student">{{k}}:{{v}}</li>
<hr/><!--遍历多个对象-->
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>电话</th>
</tr>
<tr v-for="(user,i) in users" :key="i">
<td>{{i+1}}</td>
<td v-for="value in user">{{value}}</td>
</tr>
</table>
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
args: [1,2,3,4,5],
student: {
name: "vv",
age: 19
},
users: [
{
name: "zhangshan",
age: 18,
tel: "111111"
},
{
name: "lisi",
age: 20,
tel: "222222"
}
]
}
})
</script>
2.3.事件
参数传递
<body>
<div id="app">
{{count}}
<button @click="addbtn(2)">增加2</button>
<button @click="relsbtn(2)">减少2</button><br>
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
count: 0
},
methods: {
addbtn: function (step) {
this.count+=step
},
relsbtn: function (step) {
this.count-=step
}
}
})
</script>
事件修饰符
<body>
<div id="app">
<!--keyup,当用户释放键盘上的按键时触发,-->
<!-- .enter表示,只要按下了回车键才触发-->
<input type="text" @keyup.enter="mykeyup">
</div>
</body>
<script>
new Vue({
el: "#app",
methods: {
mykeyup: function (event) {
alert("输入了:"+event.target.value)
}
}
})
</script>
2.4.计算属性
计算属性不能绑定click事件
<body>
<div id="app">
<!-- 计算属性,突出在属性两个字上,它就是一个能够将计算结果缓存起来的属性,getTime2是个属性。
这样可以大大提高效率,查询经常不变的值的时候,可以使用computed-->
{{getTime1()}}<br><!--重复调用获取的值不同-->
{{getTime2}}<br><!--重复调用获取的值相同-->
</div>
</body>
<script>
new Vue({
el: "#app",
methods: {
getTime1: function () {
return new Date()
}
},
computed: {
getTime2: function () {
return new Date()
}
}
})
</script>
2.5.watch
<body>
<div id="app">
<!--监控数据的变化-->
<input type="text" v-model="m">
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
m:"11"
},
watch: {
//当m发生改变的时候会被调用
m:function (newValue,oldValue) {
console.log(newValue+" "+oldValue)
}
}
})
</script>
3.Vue实例(对象)
直接通过对象.的方式调用属性,是来自于data或computed中的属性,但是vue对象中的el、methods等称为实例属性
3.1.ref的使用
在vue中,往往使用ref代替id属性使用。vue可以快速的通过调用ref的值来获取页面中 的某个属性
<body>
<div id="app">
<button ref="mybtn" @click="change">改变</button>
</div>
</body>
<script>
new Vue({
el: '#app',
methods: {
change: function () {
<!--通过$调用实例属性-->
this.$refs.mybtn.innerHTML="hello"
}
}
})
</script>
3.2.mount的使用
实现页面的元素和vue对象动态绑定,之前都是通过el的方式绑定
<body>
<div id="app"></div>
</body>
<script>
var v1 = new Vue({
template: "<h1>hello</h1>"
})
v1.$mount("#app")
</script>
3.3.实例的生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如created钩子可以用来在一个实例被创建之后执行代码
new Vue({
data: {
a: 1
},
created: function () {
console.log(this.a)
}
})
4.Vue组件*
4.1.使用
可以将vue对象作为一个组件,反复使用。一个组件本质上是一个拥有预定义选项的一个 Vue 实例
注册组件(全局注册)
使用组件:在被vue绑定了的html元素中才能使用组件
<body>
<div id="app">
<model1></model1>
</div>
</body>
<script>
//注册组件
Vue.component("model1", {
template: "<div><button @click='btn'>点击</button></div>",
methods: {
btn: function () {
alert("Hello")
}
}
});
new Vue({
el: '#app'
})
</script>
作为组件的Vue对象
Vue.componet("组件名",{vue对象}),这个vue对象和之前的vue对象的data实例属性写法有区别
data必须是个函数
data: function(){
return {msg: "Hello"}
}
prop
prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。
4.2.vue组件的局部注册
提高代码的复用性,万物皆组件
全局注册:被vue绑定的div中都可以使用
局部注册:在其他被vue注册的div中不能使用
<body>
<div id="app">
<model></model>
</div>
</body>
<script>
//注册组件
var model1 = {
template: "<div>{{msg}}<button @click='btn'>点击</button></div>",
data: function(){
return {msg: "Hello"}
},
methods: {
btn: function () {
alert("Hello")
}
}
};
new Vue({
el: '#app',
//绑定
components: {
"model": model1
}
})
</script>
5.搭建vue项目
5.1.vue-cli 脚手架
后端使用maven来创建项目的时候,有两个目的,一是通过maven的依赖机制能够快速管理依赖,二是通过maven来确定项目的结构
项目结构就是项目里有哪些文件和文件夹,文件夹有什么层级关系
vue-cli存放了很多常用的项目骨架,直接拿来就可以搭建一个比较成熟的项目结构目录
5.2.node.js
能够让JavaScript运行在服务端的开发平台
5.3.Vue文件
vue文件就是一个vue实例
<template>
<div id="app">
<!--Html内容-->
</div>
</template>
<script>
//暴露出默认的vue对象
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
</style>
5.4.项目中组件的全局注册
在components下建三个组件
在main.js下面导入
在App.vue下直接使用就行
5.5.本地注册
直接在App.vue里面导入
5.6.组件间的参数传递
父传子
App.vue中使用Header组件的时候,传递值
Header
子传父
Header
<template>
<div>
<h1>{{title}}</h1>
<button @click="f">点击</button>
</div>
</template>
<script>
export default {
name: "Header",
props:['title'],
methods: {
f:function () {
this.$emit("newName","子传给父的值")
}
}
}
</script>
App.vue
6.Vue发生Ajax请求(Axios)
vue本身不包含ajax请求的功能,因为vue只关注视图层
安装axios
npm install axios
解决跨域问题:
跨域指的是浏览器不能执行其他网站的脚本,是对JavaScript施加的安全限制,是浏览器的同源策略(域名、协议、端口相同)造成的
后台配置springmvc的配置文件
<!-- 接口跨域配置 -->
<mvc:cors>
<mvc:mapping path="/**"
allowed-origins="*"
allowed-methods="POST, GET, OPTIONS, DELETE, PUT"
allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
allow-credentials="true" />
</mvc:cors>
发生ajax请求
get请求
<template>
<div id="app">
<form>
账号:<input type="text" v-model="uname"><br>
密码:<input type="password" v-model="pword"><br>
<input type="submit" value="提交" @click="login">
</form>
</div>
</template>
<script>
import axios from 'axios';//导入axios
export default {
name: 'App',
data(){
return{
uname: "",
pword: ""
}
},
methods: {
login:function () {
axios.get('http://localhost:8082/login?username='+this.uname+'&password='+this.pword).then(function (response) {
console.log(response);
})
}
}
}
</script>
post请求(需要使用qs插件)
npm install qs
<template>
<div id="app">
<form>
账号:<input type="text" v-model="uname"><br>
密码:<input type="password" v-model="pword"><br>
<input type="submit" value="提交" @click="login">
</form>
</div>
</template>
<script>
import axios from 'axios';//导入axios
import Qs from 'qs'//使用qs来传post请求数据
export default {
name: 'App',
data(){
return{
uname: "",
pword: ""
}
},
methods: {
login:function () {
var name = this.uname;
var password = this.pword;
axios({
method: 'post',
url: 'http://localhost:8082/login',
data: Qs.stringify({
username: name,
password: password
})
}).then(function (resp) {
console.log(resp)
})
}
}
}
</script>
7.路由
7.1.使用步骤
在一个vue组件中实现其他组件的切换
安装路由模块
npm install vue-router -s
创建路由模块
创建静态的路由表routes.js
import Home from "@/components/Home";
import Products from "@/components/Products";
export const routes = [
{
path: '/Home',
component: Home
},
{
path: '/Products',
component: Products
}
];
在main.js中引入路由模块并使用
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'//1、引入路由模块
import {routes} from "./routes";//2、静态路由表
Vue.use(VueRouter)//3、使用路由模块
//4、创建VueRouter实例
const router = new VueRouter({
routes: routes
});
Vue.config.productionTip = false;
new Vue({
router,//5、把实例放到vue实例中
render: h => h(App),
}).$mount('#app');
在App.vue使用路由
<template>
<div id="app">
<div>
<span>
<router-link to="/Home">首页</router-link>
</span>
<span>
<router-link to="/Products">商品列表</router-link>
</span>
</div>
<!--router-view对应我们创建的两个视图,可以通过上面链接来切换-->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
7.2.路由间参数传递
在路由表中设置参数
通过router-link的to访问路径时,携带参数
在目标组件中通过$route.params.参数名接收参数
路由跳转,除了使用router-link来跳转之外,还可以在js中跳转
第二种方式:
8.使用Element-ui搭建一个登录页面
搭建环境
# 安装 vue-router
npm install vue-router -s
# 安装element-ui
npm i element-ui -S
# 安装axios
npm install axios
配置路由
在src下创建一个views文件夹里面创建一个Login.vue,里面写页面
<template>
<div>
Login..
</div>
</template>
<script>
export default {
name: "Login"
}
</script>
<style scoped>
</style>
在src下创建rouer文件夹,里面创建index.js此时该文件就是一个路由表
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
}
]
})
在main.js配置路由
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'//全局路由模块
import router from "./router";//路由表
Vue.use(VueRouter)//使用路由模块
Vue.config.productionTip = false
new Vue({
router,//5、把实例放到vue实例中
render: h => h(App)
}).$mount('#app')
在App.vue中创建视图
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
在项目中使用element-ui
在main.js中引入
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
编写前台代码
<template>
<div class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="name">
<el-input v-model="form.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item style="margin-left: 60px">
<el-button type="primary" @click="submit('form')">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import axios from "axios";
import Qs from 'qs'
export default {
name: "Login",
data() {
return {
form: {
name: '',
password: '',
},
//验证规则
rules :{
name: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur' }
]
}
}
},
methods: {
submit(formName) {
var vm = this;//在里面不能直接调用this
var name = this.form.name;
var password = this.form.password;
this.$refs[formName].validate((valid) => {
if (valid) {
axios({
method: 'post',
url: 'http://localhost:8082/login',
data: Qs.stringify({
name: name,
password: password
})
}).then(function (resp) {
if(resp.data==='success') {
//跳转页面
}else {
vm.$message.error('用户名或密码错误');
}
})
} else {
this.$message.error('用户名或密码格式不对');
return false;
}
});
}
}
}
</script>
<style scoped>
.login-box {
width: 350px;
height: 350px;
border: 1px solid #DCDFE6;
margin: 150px auto;
padding: 20px 50px 20px 20px;
border-radius: 20px;
mso-border-shadow: yes;
}
.login-title {
text-align: center;
margin-bottom: 40px;
}
</style>
登录成功后,跳转到首页
引入主页
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login'
import Home from '../views/Home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Home',
name: 'Home',
component: Home
}
]
})
实现跳转
跳转首页,并从后台显示数据
<template>
<div>
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>商品</template>
<el-menu-item-group>
<el-menu-item index="1-1">商品列表</el-menu-item>
<el-menu-item index="1-2">商品信息</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-main>
<el-table :data="users"><!--不需要使用v-for,会自动进行遍历-->
<el-table-column prop="uid" label="id" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="age" label="年龄">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "Home",
data(){
return {
users:[]
}
},
created(){
var vm = this;
axios.get("http://localhost:8082/created").then(function (resp) {
vm.users = resp.data
})
}
}
</script>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
9.路由的其他细节
9.1.嵌套路由
在路由显示的组件内部,又嵌套路由
配置路由表
比如我们在Home中加两个模块
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login'
import Home from '../views/Home'
import Products from "../views/Products"
import ProductInfo from "../views/ProductInfo";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Home',
name: 'Home',
component: Home,
children: [
{
path: '/products',//在Home中直接使用/products就能跳转
name: 'Products',
component: Products
},
{
path: '/productInfo',
name: 'ProductInfo',
component: ProductInfo
}
]
}
]
})
使用嵌套路由
9.2.路由重定向
比如点击退出,重定向到登录页面
配置路由表