vue-router使用步骤
前提:npm install vue-router 或者 vue add router
- 在router/index.js中通过Vue.use()方法注册vue-router组件(如果这个组件是一个方法,那么直接调用这个函数来注册插件,如果是一个对象,那么会调用该对象的install方法来注册插件)
- 创建router对象(根据路由规则)
- 在main.js中先导入创建好的router对象,然后通过new Vue({router}) 来注册router对象
- 在App.vue中创建路由组件的占位符,然后通过创建一些链接
动态路由
场景:在写路由规则的时候,会在路由地址后面加参数,比如/:id,常常伴随路由懒加载一起使用来提升性能(路由懒加载:点击商品链接跳转到商品详情的时候,在点击之前不加载详情的内容,点击后才会加载详情内容)
动态路由传参的方式:
方式一: 通过当前路由规则,获取数据$route.params.id
数据响应式
- 数据模型仅仅是普通的JavaScript对象,而当我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率
- vue2中的响应式原理是通过Object.defineProperty来实现的,vue3中的响应式原理是通过Proxy来实现的
- vue的响应式机制中使用了观察者模式
双向绑定
- 数据改变,视图改变;视图改变,数据也随之改变
- 我们可以使用v-model在表单元素上创建双向数据绑定
数据驱动是vue最独特的特性之一
- 开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图
数据劫持(Object.defineProperty)
- 当访问或设置vm中的成员的时候,做一些干预操作
Object.defineProperty和new Proxy
- Object.defineProperty 浏览器兼容ie8以上(不兼容ie8)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>file-loader</title>
</head>
<body>
<div id="app">hello</div>
<script>
let data = {
msg: 'hello',
count: 10
}
let vm = {}
proxyData(data)
function proxyData(data) {
Object.keys(data).forEach(key => {
Object.defineProperty(vm, key, {
enumberable: true,
configurable: true,
get() {
console.log('get:', data[key])
return data.msg
},
set(newValue) {
console.log('set:', newValue)
if(newValue === data[key]) return
data[key] = newValue
document.querySelector("#app").textContent = data[key]
}
})
})
}
</script>
</body>
</html>
Proxy
- 直接监听对象,而非属性
- ES6中新增,IE不支持,性能由浏览器优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>file-loader</title>
</head>
<body>
<div id="app">hello</div>
<script>
let data = {
msg: 'hello',
count: 10
}
let vm = new Proxy(data, {
get(target, key) {
console.log('get:', target, target[key])
return target[key]
},
set(target, key, newValue) {
console.log('set:', key, newValue)
if(target[key] === newValue) return
target[key] = newValue
document.querySelector("#app").textContent = target[key]
}
})
</script>
</body>
</html>
创建对象的方式
- let a = {}
- let a = Object.create(null)
- 小括号里的值是用来设置对象的原型,可以把对象的原型设置为null,表示这个对象没有原型属性,因此在不需要原型属性的情况下这么写提升了性能
发布订阅模式
- $on: 订阅
- $emit: 订阅
- 自定义事件,以下代码模拟自定义事件的实现机制
<script>
class EventEmitter {
constructor() {
this.subs = Object.create(null)
}
$on(eventType, handler) {
this.subs[eventType] = this.subs[eventType] || []
this.subs[eventType].push(handler)
}
$emit(eventType) {
if(this.subs[eventType]) {
this.subs[eventType].forEach(handler => {
handler()
})
}
}
}
let em = new EventEmitter()
em.$on('click', () => {
console.log(1111)
})
em.$on('click', () => {
console.log(22222)
})
em.$emit('click')
</script>
观察者模式
观察者模式是没有事件中心的,他的订阅者与发布者之间是相互依赖的。而发布订阅模式是由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在,不会互相依赖