路由基本使用
<body>
<div id="app">
<a href="#/home">首页</a>----
<a href="#/about">关于</a>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Home = {
template: `
<div>
Home 组件
</div>
`
}
const About = {
template: `
<div>
About 组件
</div>
`
}
// router 路由
// route 规则
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
})
new Vue({
el: "#app",
router
})
</script>
</body>
路由高亮 使得增加active的名称
<style>
.router-link-active {
color: red;
font-size: 50px;
}
/* 模拟第三方选中样式类 */
.active {
color: pink;
font-size: 50px;
}
</style>
</head>
<body>
<div id="app">
<!-- router-link 默认为a标签 可以通过tag设置指定标签 -->
<router-link to="/home">首页</router-link>----
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Home = {
template: `
<div>
Home 组件
</div>
`
}
const About = {
template: `
<div>
About 组件
</div>
`
}
// router 路由
// route 规则
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
],
linkActiveClass: 'active'
})
new Vue({
el: "#app",
router
})
</script>
</body>
路由重定向+404
const router = new VueRouter({
routes: [
{
path: '/',
// 路由重定向
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
},
// 404 组件一定要放在最后一项
{
path: '*',
component: NoFoundPage
}
],
linkActiveClass: 'active'
})
路由传参
<body>
<div id="app">
<router-link to="/home">首页</router-link>----
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Home = {
template: `
<div>
Home 组件 ---- {{name}}
</div>
`,
data() {
return {
name: this.$route.params.name,
}
},
// data: () => ({
// name: '',
// age: ''
// }),
created() {
console.log(this.$route.params.name)
console.log(this.$route.query.name)
// this.name = this.$route.params.name
}
}
const About = {
template: `
<div>
About 组件
</div>
`
}
const NoFoundPage = {
template: `
<div>
404
</div>
`
}
// router 路由
// route 规则
const router = new VueRouter({
routes: [
{
path: '/',
// 路由重定向
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/home/:name',
component: Home
},
{
path: '/about',
component: About
},
// 404 组件一定要放在最后一项
{
path: '*',
component: NoFoundPage
}
],
linkActiveClass: 'active'
})
new Vue({
el: "#app",
router
})
</script>
</body>
编程式路由导航
<body>
<div id="app">
<button @click="goDetail">goDetail</button>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Home = {
template: `
<div>
Home 组件 ---- {{name}}
</div>
`,
data() {
return {
name: this.$route.params.name,
}
},
created() {
// console.log(this.$route.query.name, this.$route.query.age)
console.log(this.$route.params.name, this.$route.params.age)
}
}
const NoFoundPage = {
template: `
<div>
404
</div>
`
}
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
name: 'home',
path: '/home/:name/:age',
component: Home
},
// 404 组件一定要放在最后一项
{
path: '*',
component: NoFoundPage
}
],
linkActiveClass: 'active'
})
new Vue({
el: "#app",
methods: {
goDetail() {
// this.$router.push('home')
// this.$router.push('/home')
// this.$router.push('/home?name=fly&age=18')
// this.$router.push({ path: '/home', query: { name: 'fly', age: 18 } })
// this.$router.push('/home/fly/18')
this.$router.push({ name: 'home', params: { name: 'fly', age: 18 } })
}
},
router
})
</script>
</body>
嵌套路由
<body>
<div id="app">
<router-link to="/home">首页</router-link>----
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Com1 = {
template: `
<div>
Com1 组件
</div>
`
}
const Home = {
template: `
<div>
<router-link to="/home/com1">com1</router-link>
<router-view></router-view>
</div>
`
}
const About = {
template: `
<div>
About 组件
</div>
`
}
const NoFoundPage = {
template: `
<div>
404
</div>
`
}
// router 路由
// route 规则
const router = new VueRouter({
routes: [
{
path: '/',
// 路由重定向
redirect: '/home'
},
{
path: '/home',
component: Home,
children: [
{
path: '/home/com1',
component: Com1
},
]
},
{
path: '/about',
component: About
},
// 404 组件一定要放在最后一项
{
path: '*',
component: NoFoundPage
}
],
linkActiveClass: 'active'
})
new Vue({
el: "#app",
router
})
</script>
</body>
命名式图路由
<body>
<div id="app">
<router-view class="header"></router-view>
<router-view class="main" name="main"></router-view>
<router-view class="footer" name="footer"></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Header = {
template: `
<div>
Header
</div>
`
}
const Main = {
template: `
<div>
Main
</div>
`
}
const Footer = {
template: `
<div>
Footer
</div>
`
}
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Header,
'main': Main,
'footer': Footer
}
}
]
})
new Vue({
el: "#app",
data: {
},
created() {
},
methods: {
},
router
})
</script>
</body>
前置路由
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
const Login = {
template: `
<div>
Login 组件
<button @click="login">登录</button>
</div>
`,
methods: {
login() {
// 1. 发送ajax请求 ,返回 token
// 2. 把token 保存到本地存储
localStorage.token = 'FLSJFLSJERLJFLSJFLSJ'
this.$router.push('/home')
}
}
}
const Home = {
template: `
<div>
Home 组件
</div>
`,
created() {
console.log('home')
}
}
const About = {
template: `
<div>
About 组件
</div>
`
}
const NoFoundPage = {
template: `
<div>
404
</div>
`
}
// router 路由
// route 规则
const router = new VueRouter({
routes: [
{
path: '/',
// 路由重定向
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/login',
component: Login,
meta: {
requiresAuth: true
}
},
{
path: '/about',
component: About
},
// 404 组件一定要放在最后一项
{
path: '*',
component: NoFoundPage
}
],
linkActiveClass: 'active'
})
router.beforeEach((to, from, next) => {
// if (to.path !== '/login') {
// // 1. 验证你是否登录
// console.log(localStorage.token)
// if (localStorage.token) {
// console.log(1)
// next()
// } else {
// next('/login')
// }
// } else {
// next()
// }
if (!to.meta.requiresAuth && !localStorage.token) {
next('/login')
} else {
next()
}
})
new Vue({
el: "#app",
router
})
</script>
</body>
笔记总结
readme
1、什么是vue
目前最火的前端框架
引用 mvvm 设计模式
简单、轻量、快捷的框架
指令
组件化
模块化
路由
2、库和框架的区别
-
库
小而巧,一些小的功能、可以通过某个库过渡到另一个库 jquery-->zepto
-
框架 (vue、express)
大而全,一整套的解决方案、ui、js(ajax)
3、MVC和MVVM的区别
- MVC
model (数据库连接)
view (前端页面)
-
controller (逻辑控制)
router.js / service.js
- MVVM
model (后台请求的数据,自己写的一些死数据)
view (渲染的模板区域)
view model (vm) model和view的调度者
- ps:
MVC 是站在整个项目的角度考虑
MVVM 是站在前端项目的角度考虑
4、Vue 构造函数的属性
el string 指定view的渲染区域
data object 指定model存放的位置
methods object 指定函数的存放位置
template string 指定模板
5、指令
渲染指令
- {{}} + v-cloak
v-cloak如果解决页面闪烁问题
通过 [v-cloak] :{display:none} 先把指定的元素 v-cloak 隐藏
当vue加载完毕之后把指定的 v-cloak删除
v-text
v-html
属性绑定
v-bind 简写 :
v-model
- vue中唯一一个双向数据绑定指令
- 使用场景 (表单元素和组件中使用)
- 原理
- 使用v-bind绑定值
- 使用@input绑定函数
单向数据绑定和双向数据绑定的区别 (面试题)
- 单向数据绑定
model改变view改变,不能反过来
- 双向数据绑定
model改变view改变、反之亦然
事件绑定 和 事件修饰符
- 事件绑定
- v-on 简写 @
- 事件修饰符
stop 阻止事件冒泡
prevent 阻止默认行为
capture 事件捕获
self 只阻止自己的事件
once 只阻止一次的默认行为
- 按键修饰符
- enter
样式绑定指令
- class (推荐方式)
普通数组 :class="['red','blue','active']" red、blue、active 都是在css里面定义好的
数组三元 :class="['red','blue', flag?'active':'']" flag 是在data里面定义好的布尔值
数组对象 :class="['red','blue', {active:flag}]" flag 是在data里面定义好的布尔值
对象方式 :class="{red:true,blue:true}" 对象里面的样式名可以用引号包含 key:value key是样式名 value 是布尔值
- style (几乎不用)
对象 :style="{color: red}"
数组 :style="[{color:red},{width:50px}]"
数据遍历
- v-for
普通数组
数组对象
对象
数字
- 标准写法
v-for="item in arr" :key="item.id"
v-for="(item,index) in arr" :key="item.id"
v-for="(val,key,index) in obj" :key="key"
v-for= "counnt in 8" 索引是从1开始到8
- v-for 为什么要跟随 key一起使用
给指定的标签添加唯一标识,防止页面在重新绘制的时候发生错乱,确保model和view的值保持一致
v-show、v-if
- 区别
v-show 是通过样式操作元素的显示隐藏
v-if 是通过DOM操作元素的添加删除
- 使用场景
如果大量操作使用DOM建议使用v-show
频繁点击的也建议使用v-show
条件渲染使用 v-if
vue双向数据绑定原理
- 2.x
Object.definedPeoperty(obj,'txt',{
get() {
},
set() {}
})
- 3.x
new Proxy(obj,{
get() {
},
get() {
}
})
6. 网络请求
axios 可以使用在任意的框架
vue-resource 2.0之后不更新了不建议使用
7. json-server
- 安装
npm i json-server -g
- 在项目跟目录设置json文件 data.json
{
"todos": [
{
"id": 1,
"name": "fly"
}
]
}
- 命令运行服务
json-server --watch ./data.json
--port 端口号
--host ip
json-server --port 8888 --host 10.41.157.61 ./data.json
- 常用查询语句
-
获取所有资源
-
根据id获取资源
get http://127.0.0.1:3000/hero/:id
get http://127.0.0.1:3000/hero?id=1 -
分页获取资源
-
模糊查询
-
添加
-
更新
put http://127.0.0.1:3000/hero/:id
patch http://127.0.0.1:3000/hero/:id -
删除
- 接口参数类型
query
params
body
8. 自定义指令
全局指令
Vue.directive('指令名称',obj)
Vue.directive('指令名称',callback)
私有指令
directives: {
指令名称: {
},
指令名称() {
}
}
9. 自定义过滤器
Vue.filter('过滤器名称',callback)
使用场景
属性绑定 v-bind:msg="msg|过滤器名称"
插值表达式 {{msg|过滤器名称}}
ps: 不能使用在 v-model中
10. methods/watch/computed 的区别
methods 适合用于逻辑处理,业务处理
不会缓存数据
watch 只适合监听单个数据的变化,监听路由
只适合监听单个数据的变化,当监听多个数据的时候反而变得复杂
computed 适合计算属性
会缓存数据,方便下次使用
11. vue动画
- 原生动画
需要有一个可切换的元素
使用transition 包裹切换的元素
-
设置动画的样式
起点、终点的位置、状态
动画的时间 进入 离开
- 第三方动画
引入 animate.css
需要有一个可切换的元素
-
使用transition 包裹切换的元素
设置动画类
进入 enter-active-class
离开 leave-active-class
动画时间
duration
- 列表动画
transition-group 包含动画列表
-
动画属性
appear 进入就有动画
tag 设置指定标签,默认为span
v-move 后续操作
- 半场动画
需要有一个可切换的元素
使用transition 包裹切换的元素
-
设置动画的钩子函数
before-enter
enter
after-enter
12. 组件
12.1 组件基本使用
- 定义
const Login = {}
const Login = Vue.extend({
})
- 注册
全局注册
Vue.component('组件名称',定义组件的返回值)
私有注册
- 渲染
以组件名称作为标签渲染
12.2 动态组件
- 定义
const Login = {}
const Login = Vue.extend({
})
- 注册
全局注册
Vue.component('组件名称',定义组件的返回值)
私有注册
- 渲染
以component 渲染 通过 is属性切换 ,组件切换的时候使用
12.3 异步组件 (按需引入组件)
Vue.component('组件名称',(resolve,reject)=>{
setTimeout(function(){
resolve({
template: ''
})
})
})
12.4 组件插槽
想在父组件修改子组件的ui
-
匿名插槽
<slot>默认值</slot>
<Login>
<div>修改插槽中的内容</div>
</Login>
-
具名插槽
<slot name="header">默认值</slot>
<slot name="body">默认值</slot><Login>
<div slot="header">修改插槽中的内容</div>
</Login>
- 作用域插槽
<slot name="header" :msg="'默认值'">默认值</slot>
<Login>
<div slot="header" slot-scope="scope">{{scope.msg}}</div>
<div slot="header" slot-scope="{msg}">{{msg}}</div>
</Login>
- v-slot (2.6+)
<slot name="header" :msg="'默认值'">默认值</slot>
<Login>
<template slot="header" slot-scope="scope">{{scope.msg}}</template>
<template v-slot:header="scope">{{scope.msg}}</template>
<template #header="scope">{{scope.msg}}</template>
</Login>
12.5 组件中的data为什么是一个function
12.6 组件通信
每个组件的data数据都是独立的
- 父传子
在渲染的子组件上使用 v-bind 绑定要传递的父组件的 data 数据
-
在子组件中使用 props 接受传递过来的数据
props: ['自定义的属性名称']
props: {
自定义的属性名称: {
type: ,
default:
}
}
- 子传父
在渲染的子组件上使用 v-on 监听父组件的函数
在子组件中使用 this.$emit() 调用监听的函数 ,调用的同时可以传递子组件的数据
- 兄弟传值、事件总线
b --> a
-
实例化一个空的vue
const eventBus = new Vue()
在a中使用 eventBus.$on 监听事件
在b中使用 eventBus.$emit 调用
- refs
可以获取 html DOM元素
可以获取子组件的 data 和 methods
- parent
- 可以获取父组件的 data 和 methods
- 祖先组件传子组件 provide / inject
-
在顶层组件设置
provide: {
name: '顶层数据'
} -
在顶层组件下面的子组件使用 inject 接受
inject: {
name: {}
}inject: ['name']
爷孙组件传值
listeners
在渲染的子组件上使用 v-bind 和 v-on 绑定传递和监听 爷爷的数据
在父组件中使用 v-bind="
listeners" 桥接
在son组件中
通过 $attrs 获取数据
通过$emit 调用函数
13. 路由
路由是一种对应关系
后端路由:客户端请求的URL地址 和 服务端对该地址的处理函数的对应关系
前端路由:客户端请求的Hash地址 和组件的对应关系
13.1 基本使用
使用script 引入 vue-router
定义组件
实例化路由对象 new VueRouter
配置路由规则
hash 和 component挂载路由
渲染路由
router-view 渲染
router-link 跳转