vue知识点速刷
转于自己的语雀账号,从此转移阵地,还是掘金香!
1.为什么要使用key值:
因为在改变show后,页面进行重新渲染时,会尽量复用页面上的DOM,导致已经输入的用户名的input没有清空并继续作为邮箱的input使用;为某个标签添加key值(名字任意)之后,Vue会知道是页面唯一的元素,两个key值不一样, Vue就不会尝试复用这个标签。
2.数组循环
- 为了提升循环显示的性能,会给每个循环项上加一个唯一的key值,
- 这里不是很推荐写inedx值,会频繁造作DOM元素相对应的数据,废性能,可能会导致Vue没有办法充分复用节点,一般项目中除了内容还会返回id,使用这个id作为标识`:key='item.id'
- 当我们为数组增加内容的时候,不能使用数组的下标形式添加/改变数组, 第一种响应式改变数组数据的方法:我们只能通过vue提供的7个数组变异方法来操作数组,才能够实现数据发生变化,页面也跟着变化这种响应式的方法:
7个 数组变异方法: push增加最后一项、pop删除最后一项、shift删除第一项 、unshift添加第一项、 splice(1开 始下标,1个数,添加的内容)数组的截取 、sort数组排序、 reverse数组取反;
-
- 第二种响应式改变数组数据的方法:改变数组内容并响应的方法,就是“改变引用” ,直接修改引用的list,让它指向另一个数组的地址
- 第三种set方法:第二个参数代表了数组的下标,第三个是改变的内容
Vue.set方法[全局方法]:
Vue.set(vm.userInfo , 2 , "beijing")
**vm.set方法∗∗[实力方法]:‘vm.set方法**[实力方法]:`vm.set方法∗∗[实力方法]:‘vm.set(vm.userInfo , 2, "beijing")`
- 当我们要遍历两个标签,但是又不想用div标签来包裹这两个标签循环的时候,可以使用template模板占位符,在渲染的过程中并不会真正得被渲染到页面上
3.除了数组,对象也可以进行循环
- item是键值,key是键名,index是索引这里直接修改键值,页面是可以做到响应的,
- 但是如果是添加一个键值对,就会发现只改变了数值,页面没有进行响应式改变;这个时候使用改变指向,直接重新赋值userInfo这个对象的所有值。
- Vue.set方法[全局方法]:
Vue.set(vm.userInfo , "adress" , "beijing")
- **vm.set方法∗∗[实例方法]:‘vm.set方法**[实例方法]:`vm.set方法∗∗[实例方法]:‘vm.set(vm.userInfo , "adress" , "beijing")`
4.is属性解决模板标签的bug情况
h5的规范里面,table里面一定要有tdoby,tbody里面一定要有tr,如果用row组件代替tr使用就会报错,同理还有<ul>``<ol>
里面都要放<li>
标签;<select>
标签里面要放<option>
。
- 解决方法:
<tr is='row'></tr>
,相当于调用了row这个组件
<table>
<tbody>
<tr is='row'></tr> <!-- 这个时候tr 就是 row,显示的是row中模板的内容-->
<tr is='row'></tr>
<tr is='row'></tr>
</tbody>
</table>
5.子组件中data的定义要用返回函数
data在根组件里面可以直接定义,但是在子组件中定义data时,要求必须是一个函数,返回所对应的数据内容。
- 原因:子组件会被调用很多次,每一个子组件的数据之间最好没有冲突,每个子组件都有自己的数据;通过函数返回一个数据对象的目的,就是为了让每个子组件都拥有一个独立的数据存储,不会出现多个子组件之间互相影响的情况。
// 子组件
Vue.component("filmDetail",{
data(){
return {
myinfo:"1111111111"
}
},
template:`
<div class="filminfo">
{{myinfo}}
</div>
`,
})
// 根组件
var vm = new Vue({
el: "#box",
data:{
datalist:[],
info:"111111111111111111111"
}
})
6.父组件怎么向子组件传递数据:通过属性
<counter :count='2'></counter>
父组件向子组件通过属性绑定传递值,子组件用props
属性接收 ;
count前面不加冒号,传递的是字符串;加了冒号传递的是js表达式,这里就是数字。
<div id="root">
<counter :count='2' ></counter>
<counter :count='3' ></counter>
</div>
var counter={
props:['count'],
template:'<div>0</div>'
}
var vm = new Vue ({
el : '#root',
data:{}
})
如果直接写this.count++
的话,会出现一个警告,提示不要直接修改父组件传过来的数据,所以在此,定义data里面的number作为count的副本,然后修改number的值。
<script>
var counter={ //子组件
props:['count'],
data:function(){
return {
number:this.count
}
},
template:`
<div>
<p>{{number}}</p>
<button @click="handleClick">点我number+2</button>
</div>
`,
methods:{
handleClick:function(){
this.number = this.number + 2;
}
}
}
var vm = new Vue ({ //根组件
el : '#root',
data:{
total:5
},
components:{
counter:counter
}
})
</script>
7.子组件怎么向父组件传递数据: 通过事件
this.$emit('increase',2);
这里向外触发一个increase事件,同时可以传递参数每次改变都加步长2,step;
让父组件监听,在根组件中添加监听事件handleIncrease事件,传入步长2。
<div id="root">
<span>父组件---{{total}}</span>
<counter :count='2' @increase='handleIncrease'></counter>
<counter :count='3' @increase='handleIncrease'></counter>
<div ></div>
</div>
<script>
var counter={
props:['count'],
data:function(){
return {
number:this.count
}
},
template:`
<div>
<p>{{number}}</p>
<button @click="handleClick">点我子组件number+2</button>
<button @click="changeFathertotal">点我父组件total+2</button>
<button @click="changeFathertotal1">点我父组件total+3</button>
</div>
`,
methods:{
handleClick:function(){
this.number = this.number + 2;
},
changeFathertotal:function() {
this.$emit('increase',2); // 子组件在这个地方触发
},
changeFathertotal1:function() {
this.$emit('increase',3); // 子组件在这个地方触发
}
}
}
var vm = new Vue ({
el : '#root',
data:{
total:5
},
components:{
counter:counter
},
methods:{
handleIncrease:function(step){ //可以在触发的时候传递step参数
this.total += step
}
}
})
</script>
8.非父子组件间传值(BUS总线又称发布订阅模式又称观察者模式)
<div id="box">
<child1></child1>
<child2></child2>
</div>
<script type="text/javascript">
//中央事件总线 bus
var bus = new Vue() //空的vue实例
// bus.$on bus.$emit
Vue.component("child1",{
template:`
<div>child1<button @click="handleClick">详细信息</button></div>
`,
methods:{
handleClick(){
bus.$emit("emitchildtow","出来啦少七七")
}
}
})
Vue.component("child2",{
data() {
return {
child:'还没出来'
}
},
template:`
<div>child2-订阅者----{{child}}</div>
`,
mounted() {
console.log("mounted-生命周期-dom创建完之后就会触发")
bus.$on("emitchildtow",(data)=>{
console.log("订阅者child2----",data)
this.child = data
})
}
})
var vm = new Vue({
el:"#box",
methods: {},
})
</script>
9.作用域插槽
-
什么时候用这个作用域插槽的应用场景?
-
回答:当子组件的DOM结构需要由外部传递进来的时候;子组件可以更方便地向父组件的插槽里面传数据。首先,父组件调用子组件的时候,给子组件传了一个插槽,这个插槽叫做作用域插槽:
-
必须以
<template>
标签包裹; -
同时这个插槽需要声明要从子组件接受的数据放在
slot-scope='props'
; -
还要告诉子组件一个模板的信息(接收到的数据的展示方式) ,
<li>
、<h1>
标签等对这个数据进行展示。
<body>
<div id="root">
<child>
<template slot-scope="props">
<h1>{{props.abc}}</h1>
</template>
</child>
</div>
<script>
Vue.component('child', {
data: function () {
return {
list: [1, 2, 3, 4]
}
},
template: `
<div> <ul> <slot v-for="item of list" :abc=item></slot></ul></div>`
})
var vm = new Vue({
el: '#root'
})
</script>
</body>
10.动态组件 <component :is=’type’>
实现toggle的办法:
常规方法
<div id="root">
<child-one v-if="type === 'child-one'"></child-one>
<child-two v-if="type === 'child-two'"></child-two>
<button @click='handleBtnClick'>change</button>
</div>
Vue.component('child-one', {
template: '<div>child-one</div>'
})
Vue.component('child-two', {
template: '<div>child-two</div>'
})
var vm = new Vue({
el: '#root',
data: {
type: 'child-one'
},
methods: {
handleBtnClick: function () {
this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
}
}
})
接下来尝试用动态组件实现 动态组件:根据is里面数据的变化自动加载不同的组件
<body>
<div id="root">
<component :is='type'></component> <!-- component标签是vue自带的表示动态组件的标签 -->
<button @click='handleBtnClick'>change</button>
</div>
<script>
//和上面的vue代码是一样的
Vue.component('child-one', {
template: '<div>child-one</div>'
})
Vue.component('child-two', {
template: '<div>child-two</div>'
})
var vm = new Vue({
el: '#root',
data: {
type: 'child-one'
},
methods: {
handleBtnClick: function () {
this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
}
}
})
</script>
</body>
这里使用了一个v-once的指令,在组件第一次被渲染的时候,会直接放在内存里面,性能更高,有效提高一些静态内容的展示效率;如果不加v-once的时候,每次切换,都要在底层先销毁一个组件,再创建一个组件,耗费了一定的性能。
<script>
//和上面的vue代码是一样的
Vue.component('child-one', {
template: '<div v-once>child-one</div>'
})
Vue.component('child-two', {
template: '<div v-once>child-two</div>'
})
</script>
11.Vue中router和route的区别
1.router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性
2.route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等
12.Vue中scoped的原理
- 作用:
实现组件私有化,防止全局污染,表示当前style样式只在当前组件中有效
- 原理:
它会在DOM结构和CSS样式上加上唯一的标记,保证唯一,会给标签添加一个独有的属性
给HTML的DOM节点加一个不重复属性data-v-469af010来标志唯一性
在添加scoped
属性的组件的每个样式选择器后添加一个等同与“不重复属性”相同的字段,实现类似于“作用域”的作用,不影响全局
13.Vue.$nextTick
当数据更改完毕,真实DOM渲染出来之后,才会执行
在Vue生命周期的 Created 函数进行的DOM操作一定要放在 Vue.$nextTick 的回调函数中
为了在数据变化之后等待Vue完成更新DOM,可以在数据变化之后立即使用Vue.$nextTick(callback),这样回调函数在DOM更新完成以后就会调用
14.Vue中绑定v-on的方法
- v-on绑定多个方法
以对象键值对的方式
<p v-on="{click:dbClick,mousemove:MouseClick}"></p>
- 一个事件绑定多个函数
中间以 , 号分割
<p @click="one(),two()">点击</p>
15.组件化和模块化的区别
- 1.组件开发的好处
易于复用,易于维护和查错,易于团队开发
- 2.组件化开发和模块化开发的区别
组件化开发注重复用
模块化开发是对整体业务进行模块划分
16.MVC与MVVM的区别:
MVC和MVVM的区别并不是VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。
- MVC中Controller演变成MVVM中的ViewModel
- MVVM通过数据来显示视图层而不是节点操作
- MVVM主要解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验
生命周期相关
1.什么是 vue 生命周期?有什么作用?
答:每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插件操作DOM节点,如想在页面渲染完后弹出广告窗, 那我们最早可在mounted 中进行。
2.第一次页面加载会触发哪几个钩子?
答:beforeCreate, created, beforeMount, mounted
3.简述每个周期具体适合哪些场景
答:beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
create:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
4.created和mounted的区别
答:created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
5.vue获取数据在哪个周期函数
答:一般 created/beforeMount/mounted 皆可.
比如如果你要操作 DOM , 那肯定 mounted 时候才能操作.
6.请详细说下你对vue生命周期的理解?
答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。
路由相关
1.mvvm 框架是什么?
答:vue是实现了双向数据绑定的mvvm框架,当视图改变更新模型层,当模型层改变更新视图层。在vue中,使用了双向绑定技术,就是View的变化能实时让Model发生变化,而Model的变化也能实时更新到View。
2.vue-router 是什么?它有哪些组件
答:vue用来写路由一个插件。router-link、router-view
3.active-class 是哪个组件的属性?
答:vue-router模块的router-link组件。children数组来定义子路由
4.怎么定义 vue-router 的动态路由? 怎么获取传过来的值?
答:在router目录下的index.js文件中,对path属性加上/:id。 使用router对象的params.id。
5.vue-router 有哪几种导航钩子?
答:三种,
第一种:是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
第二种:组件内的钩子
第三种:单独路由独享组件
6.route和router 的区别
答:router是VueRouter的实例,在script标签中想要导航到不同的url,使用router.push方法。返回上一个历史history用router.to(-1),route为当前router跳转对象。里面可以获取当前路由的name,path,query,parmas等。
7.vue-router的两种模式
答:hash模式:即地址栏 URL 中的 # 符号;hash模式背后的原理是window.onhashchange事件
history模式:window.history对象打印出来可以看到里边提供的方法和记录长度。利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)。
8.vue-router实现路由懒加载( 动态加载路由 )
答:三种方式
第一种:vue异步组件技术 ==== 异步加载,vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .但是,这种情况下一个组件生成一个js文件。
第二种:路由懒加载(使用import)。
第三种:webpack提供的require.ensure(),vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
vuex相关内容
1.vuex是什么?怎么使用?哪种功能场景使用它?
答:vue框架中状态管理。在main.js引入store,注入。
新建了一个目录store.js,….. export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
2.vuex有哪几种属性?
答:有五种,分别是 State、 Getter、Mutation 、Action、 Module
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex
3.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?
答:如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用。
转载自:https://juejin.cn/post/7224068169341878331