Vue
数据代理
- vm._data=data=options.data
- Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处:更加方便的操作data中的数据
- 基本原理:通过object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。
<body>
<div id="app">
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<h1>{{address}}</h1>
</div>
<script>
Vue.config.productionTip = false;
let data = {
name: "wc",
age: 18,
address: "zz"
}
let vm = new Vue({
data() {
return data;
}
})
vm.$mount("#app");
</script>
</body>
虚拟DOM和diff算法
v-if 和v-show的区别
- v-if是控制元素的创建或销毁,每次创建出来的都是新的,创建或销毁DOM元素,很耗性能。
- v-if后面的条件是false,它是惰性的,DOM元素压根不会创建
- v-show后面的条件不管是true或false,DOM元素都会创建,它是通过display来控制元素的显示或隐藏
- v-show不支持template标签,v-if支持template标签
- v-if会导致浏览器的重排(重排一定会引起重绘),v-show导致浏览器的重绘。
- 如果需要频繁控制元素的显示或隐藏,那么使用v-show,不频繁,也可以使用v-if,尽可能使用v-show
自定义指令
-
- 对象写法
-
- 函数写法 相当于对象的简写只写了bind()和update()
-
- 何时调用
//自定义指令的配置对象 函数写法 directives: { // 1.模板和自定义指令绑定时 (有了v-big="number")一上来 就执行big(); // 2.整个模板的某个数据变了 就执行big() big(element, binding) { //自定义指令所在标签元素 console.log(element); //自定义指令对象 console.log(binding); element.innerText = binding.value * 10; }, //自定义指令的配置对象 对象写法 fbind: { //1.模板和自定义指令绑定时 (有了v-big="number")一上来 就执行bind(); bind(element, binding) { element.value = binding.value }, //2.指令所在元素插入页面时 inserted(element, binding) { element.focus(); }, //3.指令所在模板被重新解析时 update(element, binding) { element.value = binding.value } } }
数组更新检测
在模型中数据是数组时,此时的数组元素被修改时不一定是响应式的
- 不是响应式的
- 通过中括号修改数组
- 通过修改数组长度修改数组
- 是响应式的
数组的方法
- push("item","item",.......): 在数组后面添加n个元素;并返回添加后的数组长度
- pop():删除数组的最后一个元素,并返回被删除的(即最后一个元素)内容;空数组返回und
- shift():删除数组的第一个元素,并返回被删除的(即最后一个元素)内容;空数组返回und
- unshift(item1,item2,.....): 在数组前面添加n个元素;并返回添加后的数组长度
- splice(index,num,item1,item2,...)index开始删除/添加元素的下标,num从下标开始(包含下标)要从前往后删除的几个元素,item从下标开始(包含下标)要从前往后添加的元素.返回包含被删除的所有元素的数组,没有删除就返回空数组
- sort(function(a,b)=>{return a-b}):升序 sort(function(a,b)=>{return b-a}):降序 返回一个包含排序后所有数组元素的数组对象 (3) [22, 33, 44, ob: Observer]
- reverse()反转数组:返回一个包含反转后所有数组元素的数组对象 (3)['打豆豆', '睡觉', '吃饭', ob: Observer]
路由配置
- 利用Hash (利用锚点(a标签)实现hash值的改变,通过hashchange事件监听location.hash的变化,使得对应的url现实不同的内容)
- 利用history Api (pushState方法,popstate事件类型)
- vue-router
vue-router
配置步骤
- 安装Vue Router:npm install vue-router@3.5.3
过滤器
通常用来格式化 视图中的第一个作为实参传入,返回值作为下一个函数的参数 可以一直通过 | (管道符) 一直向后传递过滤
<template>
<div>
<!-- 使用过滤器,需要对time时间进行格式化,进行过滤 -->
<h1>{{ time | timeFormat }}</h1>
</div>
</template>
<script>
// 引入moment moment是专门用来处理时间
import moment from "moment";
export default {
name: "MyComponent1",
props: [],
data() {
return {
time: Date.now(),
};
},
methods: {},
// 在filters选项中,可以配置局部过滤器
// 在这里配置的局部过滤器,只能在当前组件中使用
filters: {
// 定义了一个过滤器,叫timeFormat
// 在模板中,就可以使用过滤器了
timeFormat(params){
//利用moment对时间进行格式化
return 666;
//需要return一个格式化后的时间
return moment(params).format("YYYY-MM-DD")
}
},
};
</script>
生命周期
动态组件 & keep-alive组件
-
动态组件
- 根据 :is="组件名" 渲染对应组件 (定义一个状态直接可以把组件名放进去 模板中直接读取 就能找到对应的组件去渲染)
- 组件来回切换时 频繁销毁创建
- 用于tab栏切换
-
keep-alive
- 注意这个
<keep-alive>要求被切换到的组件都有自己的名字,不论是通过组件的name选项还是局部/全局注册。 - 组件实例能够被在它们第一次被创建的时候缓存下来 提高性能 还能保持组件的状态 (被选中的文章) 甚至当它未被渲染时也是如此
- keep-alive生命周期钩子 (activated )在keep-alive组件激活时调用 , (deactivated )在keep-alive组件停用时调用
- 使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。
- 该钩子在服务器端渲染期间不被调用
- 注意这个
//App组件
<template>
<div>
<button @click="HandleHome">主页</button>
<button @click="HandleLogin">登录</button>
<keep-alive>
<component :is="componentId"></component>
</keep-alive>
</div>
</template>
<script>
import Home from "./components/home.vue"
import Login from "./components/login.vue"
export default {
name: 'App',
components: {
Home,
Login
},
data() {
return {
//定义一个状态直接可以把组件名放进去 模板中直接读取 就能找到对应的组件去渲染
componentId: "Home"
};
},
computed: {
},
methods: {
//点击按钮 更换组件
HandleHome() {
this.componentId = "Home"
},
HandleLogin() {
this.componentId = "Login"
}
}
}
</script>
//Home组件
<template>
<div>
<span>我是主页面</span>
</div>
</template>
<script>
export default {
created() {
console.log("组件创建了");
},
destroyed() {
console.log("组件销毁了");
},
activated(){
console.log("在keep-alive 组件激活时调用");
},
deactivated(){
console.log("在 keep-alive 组件停用时调用");
},
}
</script>
//Login 组件
<template>
<div>
<span>我是登录页</span>
</div>
</template>
<script>
export default {
created() {
console.log("组件创建了");
},
destroyed() {
console.log("组件销毁了");
},
}
</script>
vue监测对象 (响应式对象原理简单模拟) 源码复杂得多
- 创建监测对象 防止set get 递归调用
<script type="text/javascript">
let data = {
name: "汉库克",
address: "女儿国"
}
function Observer(obj) {
//转对象为数组
let keys = Object.keys(obj)
//this 是 obs
keys.forEach((k) => {
Object.defineProperty(this, k, {
get() {
return obj[k]
},
set(val) {
obj[k] = val
}
})
})
}
//创建监测对象
let obs = new Observer(data)
let vm = {}
vm._data = data = obs
console.log(vm._data);
</script>
mixin (混入)
复用代码
- 全局混入
1.新建mixin.js文件
//导出对象
export const hunhe = {
data() {
return {
name: '祝志鹏',
age: 21
}
},
methods: {
say() {
console.log(this.name);
}
}
}
export const hunhe1 = {
data() {
return {
hobby: '蛇',
sex: "女"
}
},
methods: {
speak() {
console.log(this.sex);
}
}
}
2.在入口文件引入mixin.js
3.每个组件就可以使用了
- 局部混入
1.新建mixin.js文件
//导出对象
export const hunhe = {
data() {
return {
name: '祝志鹏',
age: 21
}
},
methods: {
say() {
console.log(this.name);
}
}
}
export const hunhe1 = {
data() {
return {
hobby: '蛇',
sex: "女"
}
},
methods: {
speak() {
console.log(this.sex);
}
}
}
2.在组件文件引入mixin.js
3.当前组件就可以使用了
- 多个混入
全局混入的多个混入
全局混入的多个混入
vm与vc的联系
插槽
<slot> 元素作为承载分发内容的出口。父组件向子组件插入想要的内容(标签,组件,文本)
- 子组件
- 父组件
疯装组件
1.自定义属性传数据渲染
2.插槽使用控制结构
3.逻辑多样