目录
第一个Vue程序
Vue官网
先要引入 vue.js,在官网复制 CDN ,或者下载 js 文件都行
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{message}}
</div>
<script>
var app = new Vue({
// element 缩写,挂载元素
el: "#app",
data: {
message: "Hello Vue!"
}
})
</script>
</body>
</html>
v-if、v-else-is、v-else
具体作用和其他语言一样
<div id="app">
<h1 v-if="flag === 'awe'">Vue is awesome</h1>
<h1 v-else-if="flag === 'no'">No no 👻</h1>
<h1 v-else>Yes yes 🤡</h1>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
// flag: "awe",
// flag: "no",
flag: "yes"
}
})
</script>
v-for
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
这里的 items 相当于 Java 中的数组,而 item 就相当于从数组中遍历出的对象,要使用其中的属性直接 对象.属性 即可
<ul id="app">
<li v-for="item in items">
{{item.message}}
</li>
</ul>
<script>
var app = new Vue({
el: "#app",
data: {
items: [
{message: '小红'},
{message: '小明'},
{message: '小李'}
]
}
})
</script>
v-on
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。以点击为例
<!-- 点击按钮,弹出弹窗,显示 message 中的内容 -->
<div id="app">
<button v-on:click="func">按钮</button>
</div>
<script>
var app = new Vue({
el: "#app",
data:{
message: "Hello Vue"
},
methods:{
func:function(){
alert(this.message)
}
}
})
</script>
使用Axios实现异步通信
第一个Axios应用程序
现在前端伪造一段 json 数据
{
"name": "百度",
"url": "http://www.baidu.com",
"page": 66,
"isNonProfit": true,
"address": {
"street": "海定区",
"city": "北京",
"country": "中国"
},
"links": [
{
"name": "Google",
"url": "http://www.geogle.com"
},
{
"name": "Sougou",
"url": "http://www.sougou.com"
}
]
}
使用 axios 来获取
<div id="app">
<div>
名称:{{info.name}}<br>
链接:{{info.url}}
</div>
<ul>
<li v-for="link in info.links">
<p>名称:{{link.name}}</p>
<p>链接:{{link.url}}</p>
</li>
</ul>
</div>
<script>
var app = new Vue({
el: "#app",
data(){
return{
info: {
name: '',
url: '',
links: []
}
}
},
mounted() {
axios.get('data.json').then(respose => this.info = respose.data)
}
})
</script>
v-bind
我们可以在标签的任意属性前面加上 v-bind,这样我们就可以将值赋给标签的属性了
例如:让上面百度的链接可以点击
v-model
使用 v-model 来实现数据的双向绑定。注意:v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。
实现和表单的数据同步显示
<div id="app">
<input type="text" v-model="message"/>
<p>Message is: {{message}}</p>
</div>
<script>
var app = new Vue({
el: "#app",
data:{
message: ""
}
})
</script>
其他的 多行文本、单选按钮、复选框、选择框 的使用查看官网即可
组件
使用 Vue.component 定义一个组件,并将 data 中的值赋给组件,具体值是如何传递的如箭头所示
计算属性
计算属性是用来声明式的描述一个值依赖了其他的值,当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新DOM。简单来说,它是一个能够将计算结果缓存起来的属性(把行为转化为了静态属性)。
使用 computed 来声明一个计算属性,注意 methods 中的方法名和 computed 中的属性名不能相同
<div id="app">
<p>当前时间:{{getCurrentTime()}}</p>
<p>当前时间属性:{{getCurrentTime1}}</p>
</div>
<script>
var app = new Vue({
el: "#app",
methods:{
getCurrentTime:function(){
return Date.now();
}
},
computed:{
getCurrentTime1:function(){
return Date.now();
}
}
})
</script>
计算属性和方法的区别
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。
插槽与自定义事件
插槽
使用 <slot> 标签来将组件进行动态拔插,下面我们将标题组件和内容组件通过插槽的方式进行插入
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in items" v-bind:item="item">
</todo-items>
</todo>
</div>
<script>
// 定义代办事项组件
Vue.component("todo", {
template:"<div><slot name='todo-title'></slot><ul><slot name='todo-items'></slot></ul></div>"
});
// 标题组件
Vue.component("todo-title", {
props:['title'],
template:"<div>{{title}}</div>"
});
// 内容组件
Vue.component("todo-items", {
props:['item'],
template:"<li>{{item}}</li>"
})
var app = new Vue({
el: "#app",
data:{
title: "标题",
items: ["吃饭", "睡觉", "看电视"]
}
})
</script>
自定义事件
根据上面案例,我们想实现在列表的每一个元素后面添加删除按钮,实现删除
我们的子组件是没办法直接调用外面的方法,因此,我们只能在子组件内定义方法,然后将该方法与外面的方法进行绑定,这里我们就要使用 this.$emit
Vue-cli
Vue-cli: 官方提供的一个脚手架(预先定义好目录结构和基础代码,与 java 中的 maven 类似),用于快速生成一个 vue 的项目模板
具体安装过程根据网上教程安装即可
Webpack
简介:是一个现代化的 JavaScript 应用程序静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将这些模块打包成一个或多个 bundle
安装:
npm install webpack webpack-cli -g
简单使用
编写下面两个 js 文件
hello.js
exports.sayHi = function(){
document.write("<div>Hello Vue3456789!</div>")
}
main.js
var hello = require("./hello");
hello.sayHi();
webpack 配置文件,必须命名为 webpack.config.js,这里只是简单使用
module.exports = {
entry: "./modules/main.js",
output: {
filename: "./js/bundle.js"
},
watch: true //检测代码的变化,也可以在打包时使用 webpack --watch 打包开启
}
在控制台中进入项目目录,使用 webpack 指令进行打包,就会出现下面文件
在 html 文件中引入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="dist/js/bundle.js"></script>
</body>
</html>
vue-router
简介:Vue Router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,让构建单页应用变得易如反掌,包含的功能有:
-
嵌套路由映射
-
动态路由选择
-
模块化、基于组件的路由配置
-
路由参数、查询、通配符
-
展示由 Vue.js 的过渡系统提供的过渡效果
-
细致的导航控制
-
自动激活 CSS 类的链接
-
HTML5 history 模式或 hash 模式
-
可定制的滚动行为
-
URL 的正确编码
简而言之,就是可以实现页面跳转的功能
安装:在想要安装的项目目录下输入下面指令
npm install vue-router --save-dev
如果报下面的错
就使用这个命令
npm install vue-router --save-dev --legacy-peer-deps
简单实现
先编写一个组件
<template>
<div>我是HelloWorld</div>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
配置路由
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '../components/HelloWorld.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/hello',
name: 'HelloWorld',
component: HelloWorld
}
]
})
main.js 中添加 router
路径跳转时,使用组件
整合ElementUI
安装依赖
router:
npm install vue-router --save-dev --legacy-peer-deps
elementui:
npm i element-ui -S
sass-loader 和 node-sass
npm install sass-loader@7.3.1 sass@1.26.5 --save-dev
//最后安装sass@1.26.5
npm install sass@1.26.5 --save-dev
安装所有依赖
npm install
简单使用
引入 element
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
显示使用
Vue.use(ElementUI);
在 new Vue 中添加
render: h => h(App)
再在 element 官网 组件 | Element 选择自己需要的组件,CTRL+C/V,修改即可
登录案例
编写登陆页面组件 Login.vue
<template>
<div>
<el-form ref="form" :model="form" class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号">
<el-input type="text" v-model="form.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">登录</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'Login',
data() {
return {
form: {
name: '',
password: ''
}
}
},
methods: {
onSubmit() {
this.$router.push("/main");
}
}
}
</script>
<style lang="scss" scoped>
.login-box{
width: 350px;
margin: 150px auto;
border: 1px solid #DCDFE6;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 30px #DCDFE6;
}
.login-title{
text-align: center;
}
</style>
主页面组件
<template>
<div>登陆成功</div>
</template>
<script>
export default {
name: 'Main'
}
</script>
<style>
</style>
配置路由
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login.vue'
import Main from '../views/Main.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/main',
name: 'Main',
component: Main
}
]
})
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App),
router,
components: { App },
template: '<App/>'
})
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
添加表单验证
需要通过 rules
属性传入约定的验证规则,并将 Form-Item 的 prop
属性设置为需校验的字段名,校验规则:async-validator
设置验证规则
设置点击登录时检测,这里只是检测是否为空,并未进行匹配
methods: {
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$router.push("/main");
} else {
this.$message({
message: '请输入用户名或密码',
type: 'warning'
});
return false;
}
});
}
}
嵌套路由
我们现在有上面一个页面,要实现顶部和导航不变,点击导航相应按钮时,只有中间内容部分发生变化。这里就要使用嵌套路由
首先编写会员等级和会员列表的组件
MemberLevel.vue
<template>
<div>
会员等级
</div>
</template>
<script>
export default {
name: 'MemberLevel'
}
</script>
<style>
</style>
MemberList.vue
<template>
<div>
会员列表
</div>
</template>
<script>
export default {
name: 'MemberList'
}
</script>
<style>
</style>
配置组件路由,因为这里是要获取到上面组件后,放在 Main.vue 中,因此使用嵌套路由 children,格式如下
参数传递
路径匹配方式
方式一:
修改路由配置:在路径中使用形式为 :id 的占位符,然后在请求路径后加上相应参数
获取参数:使用 {{$route.params.id}} 形式获取
<template>
<div>
会员等级 ID={{$route.params.id}}
</div>
</template>
方式二:
修改请求路径的形式:
props传参
在配置路由时开启 props
{
path: '/member/level/:id',
name: 'MemberLevel',
component: MemberLevel,
props: true
}
在对应组件内用 props 接收
其他和路径匹配一样
组件重定向
使用不同的路径访问同一个组件,路由中配置即可
去除路径中的 #
在 index.js 中加上 mode:'history'
处理404
使用通配符 *,来处理 404
{
path: '*',
name: 'NotFound',
component: NotFound
}
路由钩子函数和异步请求
路由钩子函数
beforeRouteEnter:在进入路由前执行
beforeRouteLeave:在离开路由前执行
在项目目录下安装 axios
npm install axios -s
在 main.js 中导入 axios
import axios from 'axios'
Vue.prototype.axios = axios
示例
<template>
<div>
会员等级 ID={{id}}
</div>
</template>
<script>
export default {
name: 'MemberLevel',
props:['id'],
beforeRouteEnter(to, from, next) {
console.log("进入会员等级页面");
next(vm => {
vm.getData();
});
},
beforeRouteLeave(to, from, next) {
console.log("离开会员等级页面");
next();
},
methods:{
getData: function(){
this.axios({
method: 'get',
url: 'http://localhost:8080/data.json'
}).then(function(repos){
console.log(repos);
}).catch(function(error){
console.log(error);
});
}
}
}
</script>
<style>
</style>
这里由于将数据存在了 tomcat 中,会出现跨域问题,在后端再解决
vuex
Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用程序的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。cookie 和 session ???
安装
在项目根目录下安装
npm install vuex --save
报错就用这个
npm install vuex --save --legacy-peer-deps
在 main.js 中引入和使用
import Vuex from 'vuex'
Vue.use(Vuex)
//每次路由跳转之前执行
router.beforeEach((to, from, next) => {
let isLogin = sessionStorage.getItem("isLogin");
if (to.path == '/logout') {
//清空
sessionStorage.clear();
//跳转到登录页面
next({
path: '/login'
});
} else if (to.path == '/login') {
//判断是否为空,不为空跳转到首页
if (isLogin != null) {
next({
path: '/main/:name'
})
}
}
next();
})
vuex操作对象
import Vue from 'vue'
import Vuex from 'Vuex'
Vue.use(Vuex)
//全局state对象,用于保存所有组件的公共数据
const state=sessionStorage.getItem('state') ? JSON.stringify(sessionStorage.getItem('state')):{
user:{
name: ''
}
};
//监听state对象值的最新状态(计算属性)
const getters={
getUser(state){
return state.user;
}
}
//唯一一个可以修改 state 值的方法(同步执行)
const mutations={
updateUser(state,user){
state.user = user;
}
}
//异步执行 mutations 中的方法
const actions={
asyncUpdateUser(context,user){
context.commit("updateUser",user);
}
}
export default new Vuex.Store({
state,
getters,
mutations,
actions
})
vuex模块化
就是将每个对象提出来
const user = {
//全局state对象,用于保存所有组件的公共数据
state: {
user: {
name: ''
}
},
//监听state对象值的最新状态(计算属性)
getters: {
getUser(state) {
return state.user;
}
},
//唯一一个可以修改 state 值的方法(同步执行)
mutations: {
updateUser(state, user) {
state.user = user;
}
},
//异步执行 mutations 中的方法
actions: {
asyncUpdateUser(context, user) {
context.commit("updateUser", user);
}
}
}
export default user;