1:v-for 与 v-if 不能用于同一级
v-for优先级高于v-if,因此哪怕我们只渲染出一小部分用户的元素(比如,你只想渲染列表中isActive属性为true的),也得在每次重渲染的时候遍历整个列表,造成计算浪费。
官网例子:
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
原因:当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,所以上述模板会进行如下运算:
this.users.map(function (user) {
if (user.isActive) {
return user.name
}
})
因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。
2:v-for 为什么要加key值
v-for渲染的时候采用就地复用策略,如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素。(在当前位置元素做更改渲染)。
当从中间插入数据的时候,会从插入数据后所有位置的数据都会发生改变,效率低。
。加上key每个节点具有唯一性,根据节点直接找到需要插入的位置,直接插入元素,更高效的更新虚拟dom树。
3:vuex 状态管理
待更新完善
state: 存储状态值
getters: 不改变状态值,派生出一些状态,比如对表进行过滤并计数
mutations: 修改状态值 同步事件
action: 修改状态值 处理异步事件
module: 模块
结合辅助函数用方便
(1)mapState mapGetter放在 computed 里,直接this.userInfo就可以获取用啦
computed: {
...mapState({
userInfo: 'userInfo'
}),
...mapGetter({
userInfo: 'userInfo'
})
(2) mapMutations和mapActions放在methods里 ,直接this. 引用即可
methods:{
...mapMutations(["init", "Jump"]),
...mapActions(["RPC"])
}
4.vue组件间传参
待更新完善(加案例)
1.父传子
1.父组件子标签中 绑定一个自定义属性
2.子组件用 props 属性接收 props:[‘自定义属性’]
2.子传父 封装组件中可用
1.父组件 在子组件标签上 添加一个自定义事件名,并绑定父组件的一个处理 函数 ,函数接收到的实参就是子组件传递的值
2.子组件中触发事件并传参
$emit触发当前实例的事件
this.$emit(“自定义事件名” ,“传递的值”)
3.兄弟间
1.Vue.prototype.bus =new Vue(); 在vue的原型对象上放一个公共的vue实例
2.this.bus.$emit(“change”,data) 在bus上发送一个事件,触发
3.在created 阶段中this.bus.$on(“change”,(data)=>{}) 监听/接收
4.爷孙间传值
待更新
5.过滤器filters
待更新完善 (过滤器是什么)
//你可以在一个组件的选项中定义本地的过滤器:
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
//或者在创建 Vue 实例之前全局定义过滤器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
6.Vue ref
待更新完善
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:可以调用组件内容方法等。
比如 调用封装的组件时 组件中有个方法
//子组件中定义一个getCode()方法
//父组件子标签中
<md-dynamic-password ref="dynamicCode" />
<script>
this.$refs.dynamicCode.getCode()
//调用了子组件中 getCode()方法
</script>
7.路由传参
待更新完善
有三种;
1:组件中:通过路由属性中的name来确定匹配的路由,通过params来传递参数。
this.$router.push({name: 'Describe',params: {
id: id }
})
跳转过来组件中: 这样来获取参数
this.$route.params.id
2: getDescribe(id) { t
this.$router.push({path: `/describe/${id}`})
路由配置
{path: '/describe/:id', name: 'Describe', component: Describe}
3:query传递的参数会显示在url后面?id=?
this.$router.push({
path: '/describe',
query: { id: id}
})
8.vue插槽
父组件向子组件分发内容 ,把父组件的内容放在子组件插槽中
1.匿名插槽
//父组件在子标签中
<template v-slot:default></template>
//子组件中
<slot ></slot>
2. 具名插槽
//父组件在子标签中
<template v-slot:名字></template>
//子组件中
<slot name=”名字”></slot>
3.作用域插槽 :父页面是否取放在子页面的数据
//父组件在子标签中
<template v-slot:todo=”slotProps ”>//可以随便命名接取的是子组件标签slot上属性数据的集合所有 :user="user"
{{slotProps.user.firstName}}
</template>
//子组件中
<slot name=”todo” :user=”user”>
{{user.lastName}} //后备内容:不提供插头时
</slot>
data(){
return{
user:{
lastName:"Zhang",
firstName:"yue"
}
}
}
9.生命周期和钩子函数
待更新完善(加缓存状态下钩子函数)
从创建组件对象开始,到所有数据渲染到页面上之后,所经历的整个过程
4个阶段8个钩子函数
a.0 beforeCreate(){}
a 创建阶段(create):创建组件对象,并创建data对象,没有虚拟dom树
a.1 created(){axios.get().then(res=>this.p1=res...)} //创建完可以进行 ajax请求数据
b.0 beforeMount(){}
b. 挂载阶段(mount):扫面页面内容建立虚拟dom树,并首次将组件的HTML和数据渲染到页面上的内容
b.1 mounted(){} //添加滚动事件
c.0 beforeUdate(){}
c 更新阶段(update):当组件的data中的变量被修改时,自动触发该阶段
c.1 updated(){}
d.0 beforeDestroy(){}
d 销毁(destroy)阶段:主动调用专门的销毁函数组建时,才触发该阶段
d.1 destroyed(){}
10.vue双向的绑定原理
加原生代码实现
vue2.x:Object.defineProperty
vue3:Proxy
11.v-if和v-show区别
(1)手段:
v-if是动态的向DOM树内添加或者删除DOM元素;
v-show是通过设置DOM元素的display样式属性控制显隐;
(2)编译过程:
v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;
v-show只是简单的基于css切换;
(3)编译条件:
v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载);
v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
(4)性能消耗:
v-if有更高的切换消耗;
v-show有更高的初始渲染消耗;
(5)使用场景:
v-if适合运营条件不大可能改变;
v-show适合频繁切换
12.watch:监视函数
待更新完善(监听路由变化,vuex state值变化)
a. 什么是: 自动监视data中一个模型变量的值的变化。只要模型变量的值发生改变,就自动执行监视函数!
b. 何时: 只要变量值发生改变,希望立刻执行查询操作时,就用监视函数
配合着防抖用
new Vue({
el:"#app",
data:{
kws:""
},
methods:{
...
},
watch:{
kws(){ //函数名必须以监视的变量命名
this.kws
}
},
computed:{
属性名(){
//计算过程
return 返回值
}
}
})
13.computed:计算属性:
待更新完善
不实际保存属性值,它的属性值,需要根据其他属性计算获得。
如果页面上想要的值,数据库或服务端没有直接提供,但是,可以根据现有的数据计算获得,就可用计算属性 (必须return返回)
12.13 watch computed 区别 computed和方法的区别
computed和方法
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的**响应式依赖进行缓存的**。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
watch computed
1.区别
watch 1.属性监听 监听属性的变化
函数里有倆个参数
deep:true 深度监听(可以监听对象里的属性)
immediate:true 页面加载会立即执行;
支持异步;
监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
computed:1.计算属性通过属性计算而得来的属性;
不支持异步;
必须要return返回结果
2.使用场景
computed
当一个属性受多个属性影响的时候就需要用到computed
最典型的例子: 购物车商品结算的时候
watch
当一条数据影响多条数据的时候就需要用watch
搜索数据
14.nexttick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
// DOM 更新了
})
15 $emit 和 $on 与 $once
$emit 触发当前实例上的事件。附加参数都会传给监听器回调。
$on 监听当前实例上的自定义事件。事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
// 兄弟间穿参 创建一个公共的vue实例 通过实例传递参数
$once 与$on功能一样
监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
16:路由守卫 7个
获取当前路由信息(进功能验证登录信息等)