Vue
Soc:关注点分离原则
HTML+CSS+JAVASCRIPT
网络通信:axios
页面跳转:vue-router
状态管理:vuex
只关心视图层
vm:数据双向绑定
计算属性 :Vue特点
前端三大框架
1. JQuery:
2. Angular :前端MVC
3. React:虚拟DOM(模拟DOC),放在内存中操作
Vue:集大成者(Angular ,React)
Axios:前端通信框架
JS构建工具:
- Bable:JS编译工具
- WebPack:模块打包工具
三端统一(PC:,Android:.apk,IOS:ipa)调用硬件:GPS,陀螺仪闪光灯,相机
大前端时代:MV*时代
MVC(同步通信为主):Model,View,Controller
MVP(异步通信为主):Model,View,Presenter
MVVM(异步通信为主):Model,View,View Model
View Model 双向绑定层。
1,循环-判断
1.1 判断 :v-if v-else-if v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueTest</title>
</head>
<body>
<div id="app">
<h1 v-if="type==='a'">A</h1>
<h1 v-else-if="type==='b'">B</h1>
<h1 v-else-if="type==='c'">C</h1>
<h1 v-else>in -> defghijklmnopqrstuvwxyz</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
type: 's'
}
})
</script>
</body>
</html>
1.2 循环:v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueTest</title>
</head>
<body>
<div id="app">
<li v-for="item in items">
{{item.message}}
</li>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
items: [
{message: "宇宙伟"},
{message: "黄旭伟"},
{message: "哈哈哈"},
{message: "哈哈哈"},
{message: "哈哈哈"},
{message: "哈哈哈"},
{message: "哈哈哈"}
]
}
})
</script>
</body>
</html>
2,事件处理 v-on
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Domo-04</title>
</head>
<body>
<div id="app">
<button v-on:click="say">Click Me</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "宇宙伟大奥秘"
},
methods: {
say: function () {
alert(this.message)
}
}
});
</script>
</body>
</html>
3,视图
3.1.,双向绑定
3.1.1,文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-05</title>
</head>
<body>
<div id="app">
输入的文本:<input type="text" v-model="message">
<!-- 输入的文本:<textarea v-model="message"></textarea>-->
<br>
{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "宇宙伟大奥秘"
}
});
</script>
</body>
</html>
3.1.2,下拉框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-05</title>
</head>
<body>
<div id="app">
下拉框:
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
你选中了:{{selected}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
selected: 'A'
}
});
</script>
</body>
</html>
4,组件
4.1自定义标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-06</title>
</head>
<body>
<div id="app">
<wei v-for="item in items" v-bind:xu="item"></wei>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
'use strict'
Vue.component("wei", {
props: ['xu'],
template: '<li>{{xu}}</li>'
})
var vm = new Vue({
el: "#app",
data: {
items: ["A", "B", "C", "D"]
}
})
</script>
</body>
</html>
5,网络通信
Axios:用在浏览器或Node JS的异步通信框架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-07</title>
<!--解决闪烁问题-->
<style>
[v-clock] {
display: none;
}
</style>
</head>
<body>
<div id="vue" v-clock>
<div>{{info.name}}</div>
<div>{{info.address.country}}</div>
<a v-bind:href="info.url">bilibiliGo</a>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#vue',
data() {
return {
//请求的返回参数必须和JSON字符串一样
info: {
name: null,
address: {
street: null,
city: null,
country: null
},
}
}
},
mounted() {
axios.get('../data.json').then(response => (this.info = response.data))
}
})
</script>
</body>
</html>
6,计算属性
计算出来的结果,保存在属性中,内存中运行:虚拟DOM,可以想象成缓存
用属性的方式实现方法的功能,这两者不能同名
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
</head>
<body>
<div id="app">
<p>currentTime1:{{currentTime1()}}</p> //调用方法有括号
<p>currentTime2:{{currentTime2}}</p> //调用属性没有括号
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello cosmos"
},
methods: {
currentTime1: function () {
return Date.now();
}
},
computed: {
currentTime2: function () {
return Date.now();
}
}
});
</script>
</body>
</html>
与狂神的不同点
currentTime1,调用自身,调用message都刷新时间戳
currentTime2,调用自身不刷新时间戳,调用message后刷新时间戳
结论:
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点。
计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销。
7,内容分发
7.1 slot:插槽:动态插拔
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-08</title>
<body>
<div id="vue">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
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 vm = new Vue({
el: '#vue',
data: {
title: "java系列",
todoItems: ["java1", "java2", "java3", "java4"]
}
});
</script>
</body>
</html>
7.2 自定义事件
this.$emit(‘自定义事件’,参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo-08</title>
<body>
<div id="vue">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems"
:item="item" v-bind:index="index" v-on:remove="removeItems(index)" :key="index"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
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', 'index'],
template: '<li>{{index}}---{{item}}<button @click="remove">delete</button>\n</li>',
methods: {
remove: function (index) {
this.$emit('remove', index);
}
}
});
var vm = new Vue({
el: '#vue',
data: {
title: "java版本",
todoItems: ["java1", "java2", "java3", "java4"]
},
methods: {
removeItems: function (index) {
console.log("delete" + this.todoItems[index]);
this.todoItems.splice(index, 1);
}
}
});
</script>
</body>
</html>
8,webpack
一个因为浏览器无法兼容ES5以上版本而出现的打包工具。
hello.js
exports.sayHi = function () {
document.write("<h1>ES6</h1>>")
}
main.js
var hello = require("./hello");
hello.sayHi();
webpack.config.js
module.exports = {
entry: './modules/main.js',
output: {
filename: "./js/bundle.js"
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack</title>
</head>
<body>
<script src="dist/js/bundle.js">
</script>
</body>
</html>
9,vue -router
路由管理器
作业于Vue的页面跳转
注意点:需要到myvue目录下执行npm run dev指令
一个点击运行程序后自动下载App.vue的问题:
可能原因:因为IDEA默认跳转到http://localhost:63342/myvue/src/App.vue?_ijt=8o740dblvgol1hegogqotq85eu端口,这个端口无法自动跳转就下载了App.vue。
需要手动跳转localhost:8080。
暂时没有找到解决方法
10,ElementUI+Vue
login.vue
<template>
<div>
<el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号" prop="username">
<el-input type="text" placeholder="请输入账号" v-model="form.username"/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"/>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
</el-form-item>
</el-form>
<el-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>请输入账号和密码</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
username: '',
password: ''
},
//表单验证,需要再el-form-item 元素中增加prop属性
rules: {
username: [
{required: true, message: '账号不能为空', trigger: 'blur'}
],
password: [
{required: true, message: '密码不能为空', trigger: 'blur'}
]
},
//对话框显示和隐藏
dialogVisible: false
}
},
methods: {
onSubmit(formName) {
//为表单绑定验证功能
this.$refs[formName].validate((valid) => {
if (valid) {
//使用 vue-router路由到指定页面,该方式称之为编程式导航
this.$router.push("/main");
} else {
this.dialogVisible = true;
return false;
}
});
}
}
}
</script>
<style lang="scss" scoped>
.login-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 180px auto;
padding: 35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.login-title {
text-align: center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main'
import Login from '../views/Login'
Vue.use(Router);
export default new Router({
routes: [
{
path: '/main',
component: Main
},
{
path: '/login',
component: Login
}
]
});
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(router);
Vue.use(ElementUI);
new Vue({
el: '#app',
router,
render:h =>h(App)
})
App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
Main.vue
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
记得在package.json给sass降级
"sass-loader": "^7.3.1",
11,嵌套路由
关键字:children
Main.vue
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main'
import Login from '../views/Login'
import UserList from '../views/user/List'
import UserProfile from '../views/user/Profile'
Vue.use(Router);
export default new Router({
routes: [
{
path: '/main',
component: Main,
children: [
{
path: '/user/profile',
component: UserProfile
},
{
path: '/user/list',
component: UserList
}
]
},
{
path: '/login',
component: Login
}
]
});
12,参数传递
12.1 直接传值
无法传入id
Main.vue
<router-link v-bind:to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
index.js
path: '/user/profile/:id',
name: UserProfile,
component: UserProfile
目前没有解决
12.2 props:解耦
13,重定向:redirect
{
path:'/goHome',
redirect:'/main'
}
14,路由钩子与异步请求
14.1 路由钩子:
beforeRouteEnter: (to, from, next) => {
console.log("进入路由");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("离开路由");
next();
},
beforeRouteUpdate: (to, from, next) => {
}
-
to:路由将要跳转的路径信息
-
from:路由跳转前的路径信息
-
next:路由的控制参数
- next():跳转到下一个页面
- next(’/path’):改变路由的跳转方向,跳到另一个路由
- next(‘false’):返回原来的页面
- next((vm)=>{}):仅在beforeRouteEnter中可用,vn是组件实例。
14.2 在钩子函数中使用异步请求
记得在mian.js导入Axios模块
import axios from 'axios';
import VueAxios from 'vue-axios';
Vue.use(VueAxios,axios);
Profile.vue中axios部分
methods: {
getData: function () {
this.axios({
method: 'get',
url: "http://localhost:8080/static/mock/data.json"
}).then(function (response) {
console.log(response)
})
}
}