vue2面试题

vue2x

  1. 生命周期有哪些?发送请求在那里

beforeCreate/created、beforeMounte/mounted、beforeUpdate/Updated、beforeDestory/destoryrd

2.发送请求为什么不在beforeCreate里?beforeCreate和created有什么区别?

如果请求是在methods里封装好的,在beforeCreate调用的时候,beforeCreate阶段是获取不到methods里面的方法。

3.进入组件会执行那些生命周期?

beforeCreate--created--beforeMount--mounted

4.进入组件会执行那些生命周期?

beforeCreate--created--beforeMount--mounted

5.父组件引入子组件,生命周期执行顺序是?

父:beforeCreate--created--beforeMount
子:beforeCreate--created--beforeMount--mounted
...
父:mounted

6.keep-alive

缓存当前组件

7.加入keep-alive会执行那些生命周期?

beforeCreate--created--beforeMount--mounted--activated切换组件会执行activated

8.在哪些情况下使用过那些生命周期?

created:单组件请求,或者请求的数据可以改变dom的渲染
mounted:子组件先于父组件请求,或者请求数据不会引起dom的重排
activated:多次进入相同的页面,可以判断页面的id是否相等,不相等就发请求
destroyed:关闭页面时记录视频播放的位置,下次打开时从记录位置开始播放

9.组件的通信方式

父传子:
父组件绑定,子组件通过props接收,但不能直接修改父组件的数据。
通过$parent直接获取父组件的值,可以直接修改父组件的数据。
通过依赖注入传值。
子传父:
通过事件的$emit()传递。
通过$children[0].xxx或者通过子组件身上的ref属性this.$refs.xxx.value
兄弟传值:
通过新的vue实例来中转
通过消息订阅与发布
通过全局事件总线$bus
通过vuex

10.子组件直接修改父组件的值?

子组件中用this.$parent去修改

11.依赖注入,provoid/inject

父组件:provoid(){return {value:'xxx'}}
子组件:inject:['value']

12.父组件直接修改子组件数据

<List ref='child'></List>
this.$refs.child.xxx='xxxx'

13.slot插槽

匿名插槽
居名插槽
作用域插槽

14.如何封装组件?

15.vuex有哪些属性

state:全局共享属性
getters:state的监听属性,对属性进行二次计算
actions:异步,存放异步方法
mutations:唯一可以修改state的方法,同步操作,存放同步方法
modules:将vuex模块化

16.vuex使用state值

this.$store.state.xxx
辅助函数:
    import {mapState,mapGetters} from 'vuex'
    computed:{
        ...mapState(['xxx'])
    }
    this.$store.state.xxx
区别:使用this.$store.state.xxx可以直接修改state的值
    使用辅助函数不可以直接修改state的值

17.vuex中getters属性

 this.$store.getters.xxxx
 import {mapGetters} from 'vuex'
 computed:{
     ...mapGetters(['xxxx'])
 }
 {
    
    {xxx}}

18.vuex的mutations和actions的区别

相同点:mutations和actions都是存放全局方法的,这个全局的方法return的值拿不到
区别:
mutations是同步
actions返回的是一个Promise对象,可以执行异步操作
mutations是来修改state的值,actions是用来提交mutations

19.Vuex的持久化存储

vuex本身不是持久化存储,他是一个状态管理的仓库。
用localstorage
使用插件

20.路由的模式

hash模式:#,找不到页面时不会给发送请求,打包后自测可以看到内容
history模式:/,找不到页面时会发送请求,打包后自测看不到内容

21.导航故障,本页面跳转本页面

//mian.js
import VueRouter from 'vue-router'
const routerPush = VueRouter.prototype.push
VueRouter.prototype.push = function (location){
    return routerPush.call(this,location).catch(error=>error)
}

22.route和router的区别

$router:路由实例对象,和整个路由的属性和方法
$route:包含当前路由信息对象

23.导航守卫

全局守卫:
    brforeEach路由进入之前
    afterEach路由进入之后
路由独享守卫:
    beforeEnter路由进入之前
组件内守卫:
    beforeRouteEnter路由进入之前
    beforeRouteUpdate路由更新之前
    beforeRouteLeave路由离开之前

24.$nextTick

返回的参数是一个函数,是异步的,获取更新后的dom

25.数据定义在return里面和外面的区别

外面单纯修改数据是不可以的,因为没有被getter和setter
里面的可以修改数据,被getter和setter了

26.computed计算属性

computed计算的结果值可以被修改,需要通过get/set写法。 

27.watch

监听属性,发生改变才执行
深度监听需添加deep:true

28.methods和computed的区别

computed有缓存机制,methods没有缓存机制

29.如何自定义指令

全局:
    //main.js
    Vue.directive('demo',{
        inserted:function(a,b,c){
            console.log(a,b,c)
        }
    })
    v-demo='123'
局部:
    export default {
        directives:{
            demo:{
                bind:function(el){
                    console.log(1)
                }
            }
        }
    }

30.v-for和v-if的优先级

vue2:v-for>v-if
vue3:v-if>v-for

31.$nextTick原理

异步行为
$nextTick(callback){
    return Promise.resolve().then(()=>{
        callback();
    })
}

32.vue数据驱动的原理

<div id='app'>
    <h1>{
    
    {str}}</h1>
    {
    
    { str }}
    <p>{
    
    {b}}</p>
    <button @click='btn'></button>
    <input name='' type='' v-model='str'/>
</div>
<script type="text/javascript" src="vue.js"></script>
<script type='text/javascript'>
    new Vue({
        el:'#app',
        data:{
            str:'n你好',
            b:'这是柒月北辰定义的data数据'
        },
        beforeCreate(){},
        created(){},
        beforeMount(){},
        mounted(){},
        methods:{
            btn(){
                alert(this.str)
                this.str='12345'
            }
        }
    })
</script>
class Vue{
    constructor(options){
        this.$options=options;
        //生命周期
        if(typeof options.beforeCreate=='function'){
            options.beforeCreate.bind(this)();
        }
        //获取data对象
        this.$data=options.data;
        this.proxyData();
        this.observe();
        if(typeof options.created=='function'){
            options.created.bind(this)();
        }
        if(typeof options.beforeMount=='function'){
            options.beforeMount.bind(this)();
        }
        if(typeof options.mounted=='function'){
            options.mounted.bind(this)();
        }
        //获取el节点
        this.$el=document.querySelector(options.el);
        //解析模板的方法
        this.compile(this.$el);
    }
    proxyData(){
        for(let key in this.$data){
            Object.defineProperty(this,key,{
                get(){
                    return this.$data[key];
                },
                set(val){
                    this.$data[key]=val;
                }
            })
        }
    }
    //this.str生效并修改
    observe(){
        for(let key in this.$data){
            let value=this.$data[key];
            let that=this;
            Object.defineProperty(this.$data,key,{
                get(){
                    return value;
                },
                set(val){
                    value=val;
                    if(that.$watchEvent[key]){
                        that.$watchEvent[key].forEach((item,index)=>{
                            item.update();
                        })
                    }
                }
            })
        }
    }
    compile(node){
        node.childNodes.forEach(item,index)=>{
            //元素节点
            if(item.nodeType==1){
                if(item.hasAttribute('@click')){
                    let vmKey=item.getAttribute('@click'.trim());
                    item.addEventListener('click',(event)=>{
                        this.eventFn=this.$options.methods['vmKey'].bind(this);
                        this.eventFn(event);
                    })
                }
                //v-model原理实现
                if(item.hasAttribute('v-model')){
                    let vmKey=item.getAttribute('v-model'.trim());
                    if(this.hasOwnProperty(vmKey)){
                        item.value=this[vmKey];
                    }
                    item.addEventListener('input',(event)=>{
                        this[vmKey]=item.value;
                    })
                }
                if(item.childNodes.length>0){
                    this.compile(item);
                }
            }
            //文本节点
            if(item.nodeType==3){
                let reg=/\{\{(.*?)\}\}/g;
                let text=item.textContent;
                //给节点赋值
                item.textContent=text.replace(reg,(match,vmKey)=>{
                    vmKey=vmKey.trim();
                    if(this.hasOwnProperty(vmKey)){
                        //this.str生效并修改
                        let watch=new Watch(this,vmKey,item,'textContent');
                        if(this.$watchEvent[vmKey]){
                            this.$watchEvent[vmKey].push(watch);
                        }else{
                            this.$watchEvent[vmKey]=[];
                            this.$watchEvent[vmKey].push(watch);
                        }
                    }
                    return this.$data[vmKey];
                })
            }
        }
    }
}
//this.str生效并修改
class Watch{
    constructor(vm,key,node,attr){
        this.vm=vm;
        this.key=key;
        this.node=node;
        this.attr=attr;
    }
    update(){
        this.node[this.attr]=this.vm[this.key];
    }
}

33.双向数据绑定原理

通过Obiect.defineProperty()劫持数据发生的改变,如果数据发生改变(在set中进行赋值),触发update方法进行更新节点内容,从而实现了数据双向绑定的原理。

34.什么是mvvm

model-view-viewModel

35.axios请求的封装

axios.get('http://xxxx?a=1&b=2')
axios.post('http://xxxxx',{
    a:1,
    b:2
})
axios({
    url:'xxx',
    params:{},
    data:{},
    method:'get',
    haeaders:{},
    timeout:5000,
    responseType:'json--响应的数据,默认json'
})
npm install axios -S
import axios from 'axios'
方法一:
import axios from 'axios'
axios.get('http://xxxx?a=1').then(res=>{
    
})
方法二:
import axios from 'axios'
axios({
    url:'http://xxxxxxxx',
    params:{
        a:1
    },
    methods:'get'
}).then(res=>{
    
})
开发环境解决跨域:
//vue.config.js
devServer:{
    proxy:'http://xxxxxx:3000'
}
//使用
axios.get('/list').then(res=>{})
封装axios
import axios from 'axios'
const instance=axios.create({
    //baseUrl:'http://xxxxxx.com'
    baseUrl:process.env.VUE_APP_TITLE=='schj'?process.env.VUE_APP_BASE_API:''
});
//添加请求拦截器
instance.interceptors.request.use(function(config){
    //在请求之前做些什么
    return config;
},function(error){
    return Promise.reject(error);
});
//添加响应拦截器
instance.interceptors.response.use(function(response){
    //对相应数据做点什么
    return response.data;
},function(error){
    return Promise.reject(error)
});
export default instance;
api解耦封装
import request from 'util/request';
export function reqSearch(data){
    return request({
        url:'/api/course/search',
        method:'post',
        data
    })
}
//使用
import {reqSearch} from '/api'
reqSearch({a:1,b:2})
生产环境打包后配置代理不生效----可配置环境变量解决
env.development文件
    VUE_APP_TITLE=开发环境
    VUE_APP_BASE_API='https://xxxxxxxx'
env.production文件
    VUE_APP_TITLE=生产环境
    VUE_APP_BASE_API='https://xxxxxxxx'
调用
process.env.VUE_APP_BASE_API

猜你喜欢

转载自blog.csdn.net/weixin_49662044/article/details/129085783