likes
comments
collection
share

vue知识点速刷

作者站长头像
站长
· 阅读数 37

转于自己的语雀账号,从此转移阵地,还是掘金香!

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")`
  1. 当我们要遍历两个标签,但是又不想用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
评论
请登录