zoukankan      html  css  js  c++  java
  • 【前端大神面考面试官系列】入门Vue全家桶

    (给达达前端加星标,提升前端技能

    面试官问:Vue如何安装的呢?

    达达回答:Vue的安装可以从两个方面进行安装,第一种是CDN引入,第二种是NPM安装。

    CDN引入

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    

    NPM安装

    npm install vue
    

    面试官问,如何创建Vue项目?

    达达写下代码:

    创建项目

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue入门之Helloworld</title>
        <!--引入Vue库-->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <!--创建一个Div-->
        <div id="app">
            <!--Vue的模板的绑定数据的方法,用两对花括号进行绑定Vue中的数据对象的属性 -->
            {{message}}
        </div>
    
    
        <!--创建Vue的对象,并把数据绑定到上面创建好的div上去。-->
        <script type="text/javascript">
            var app=new Vue({ // 创建Vue对象。Vue的核心对象。
                el:'#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器
                data:{    // data: 是Vue对象中绑定的数据
                    message:'hello Vue!' // message 自定义的数据
                }
            })
    </script>
    </body>
    </html>
    

    输出的结果:

    hello Vue!
    

    面试官问:v-if和v-show的区别是?

    达达回答:

    内部指令

    v-if用于显示与隐藏的元素

    <div v-if="isShow">达达前端</div>
    

    v-else,v-if不是它,就是它v-else

    <div v-else>达达前端</div>
    

    v-show

    <div v-show="isShow">你好</div>
    

    v-else-if

    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else-if="type === 'C'">C</div>
    <div v-else>Not A/B/C</div>
    

    v-if和v-show的区别是:

    v-if用于元素的被销毁和重建,使用这个指令开销较为高,在运行过程中,尽量用在很少改变时的情况下使用。v-if元素销毁和存在

    v-show的用法,这个指令的使用开销较小,在常频繁地切换使用

    面试官问:内部指令的用法有哪些,怎么用呢?

    达达回答:好,慢慢讲述。

    v-for的用法

    <!-- 模板 -->
    <div id="app">
        <ul>
            <li v-for="item in items">
                {{item}}
            </li>
        </ul>
    </div>
    
    
    <!--JS代码 -->
    <script type="text/javascript">
        var app=new Vue({
            el:'#app',
            data:{
                items:[ 1, 2, 3, 4]
            }
        })
    </script>
    

    对象遍历

    <!-- 模板 -->
    <div id="app">
        <ul>
            <li v-for="(value, key, index) in object">
            {{ index }}. {{ key }} - {{ value }}
            </li>
        </ul>
    </div>
    
    
    <!--JS代码 -->
    <script type="text/javascript">
        var app=new Vue({
            el:'#app',
            data:{
                object: {
                    firstName: 'dada',
                    lastName: 'qianduan'
                }
            }
        })
    </script>
    

    v-text的出现为了解决{{xx}}这个取值的问题,当网络很慢的情况下,或者是运行时出错的情况下,页面显示为{{xxx}}。

    <div>{{ message }}</div>
    <!-- 一样的 -->
    <div v-text="message"></div>
    

    v-html指令是用于输出html代码

    <span v-html="msgHtml"></span>
    

    v-on的用法

    // html
    <div>{{count}}</div>
    <button v-on:click="add">加</button>
    
    
    // JS
    data:{
        count: 1
    },
    methods: {
        add() {
            this.count++;
        }
    }
    

    缩写

    <button @click="add">加</button>
    

    v-model的用法,model都需要在data中声明初始值:

    data: {
        count: 1,
    }
    

    input的用法

    <input type="text" v-model="message">
    

    textarea

    <textarea  cols="30" rows="10" v-model="message"></textarea>
    

    checkbox

    <input type="checkbox" id="first" value="1" v-model="status">
    <label for="first">有效</label>
    
    
    <input type="checkbox" id="second" value="2" v-model="status">
    <label for="second">无效</label>
    
    
    <div>状态:{{status}}</div>
    

    radio

    <input type="radio" id="one" value="男" v-model="sex">
    <label for="one">男</label>
    
    
    <input type="radio" id="two" value="女" v-model="sex">
    <label for="one">女</label>
    
    
    <div>性别:{{sex}}</div>
    

    select

    <select v-model="selected">
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>
    
    
    <div>Selected: {{ selected }}</div>
    

    v-bind方法

    // html
    <img v-bind:src="imgSrc"  width="200px">
    
    
    // js
    data: {    
        imgSrc:''
    }
    

    缩写

    <img :src="imgSrc"  width="200px">
    

    v-pre方法,用这个指令可以直接跳过vue的编译,直接输出原始值,如果在标签中加入v-pre就不会输出vue中的data值。

    <div v-pre>{{message}}</div>
    

    v-cloak可以在vue渲染时指定的整个dom后才进行显示,必须和css样式一起用

    // css
    [v-cloak] {
        display: none;
    }
    
    
    // html
    <div v-cloak>{{message}}</div>
    

    v-once只能显示一次,第一次渲染的值就不会改变了

    <div v-once>{{message}}</div>
    

    面试官问:你知道Vue生命周期吗?

    达达回答:

    new Vue() 实例化对象,init events & lifecycle 初始化,事件和生命周期

    beforeCreate组件实例刚被创建,还没有实例化之前,执行一些初始化的操作,可以制作加载动画

    init injections & reactivity 初始化,依赖注入和校验

    created组件实例创建完成,属性已经绑定,但是dom还没有生成,$el属性还不存在,页面未被展示,结束加载动画,发起异步网络请求

    has"el" option? no 判断是否存在el属性,如果有,则继续编译,如果没有,则停止编译,生命周期结束,知道在该vue实例上调用vm.$mount(el),即被唤醒继续执行编译,如果注释掉“el”,等程序到create就停止了

    判断是否有template,如果有,则将其编译成render函数,如果没有,则将外部的HTML作为模板编译,template中的模板优先级高于outer html 的优先级。

    yes的路线,compile template into render function

    如果tremplate中组件的话,执行render方法渲染组件内容

    compile el's outerhtml as template

    beforeMount,完成虚拟dom配置,模板已经被编译,把data里面的数据和模板生成html,此时还没有挂载html到页面上

    create vm.$el and replace "el" with it,给vue实例对象添加$el成员,并且替换掉挂载的dom元素

    mounted,用上面编译好的html内容替换el属性指向dom对象,方法结束后,dom结构完成,页面显示出来,发起网络请求

    Mounted,when data changes,beforeUpdate,当vue发现data中的数据发生了改变,会触发对应组件的重新渲染,一般在组件发生更新之前,调用这个函数,页面还不会展示修改的内容,但虚拟dom已经配置修改

    virtual dom re-render and patch,重新渲染虚拟dom并通过diff算法对比vonde节点差异更新真实dom,updated,组件更新后,此方法执行后,修改后的页面展现出来,即为view重新渲染,数据更新

    when wm.$destroy() is called,beforeDestroy,组件实例销毁前调用,实例仍然完全可用

    teardown watchers, child components and event listeners 拆卸观察者,子组件,事件监听者

    destroyed,在vue实例销毁后调用,实例指示的所有东西都会被解除绑定,所有的事件监听都会被移除,所有的子实例都会被销毁

    面试官问:在vue中常用的语句有哪些

    达达回答:好的,请认真听讲

    computed计算属性,用于对原数据进行修改

    computed: {
        newPrice () {
            return '¥' + this.price + '元';
        }
    }
    

    methods方法属性,用于绑定方法

    methods:{
        add (num) {
            this.count += num;
        }
    }
    

    watch数据变化监听器

    watch: {
        question(val, oldVal) {
            console.log('new: %s, old: %s', val, oldVal);
        }
    }
    

    filters 过滤器

    filters: {
        filterA(value) {
            return value.toUpperCase();
        }
    }
    

    mixins用于减少代码污染,减少代码量,实现代码重用

    var addLog={
        updated:function(){
            console.log("数据放生变化,变化成"+this.count+".");
        }
    }
    
    
    var app = new Vue({
        el:'#app',
        data:{
            count: 100
        },
        // 混入
        mixins: [addLog]
    })
    

    extends用于扩展,对构造器进行扩展

    var extendObj ={
        created: function(){
            console.log("我是");
        }
    }
    
    
    var app = new Vue({
        el:'#app',
        data:{
        },
        // 扩展
        extends: extendObj
    })
    

    面试官问,你知道哪些实例事件吗?

    达达回答,vue有实例属性,实例方法,实例事件

    $on接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法
    
    
    app.$on('reduce',function(){
        console.log('执行了reduce()');
        this.count--;
    });
    
    
    app.$once('reduceOnce',function(){
        console.log('只执行一次的方法');
        this.count--;
    });
    
    
    function off(){
        console.log('关闭事件');
        app.$off('reduce');
    }
    
    
    function reduce() {
        // 事件调用
        console.log('emit事件调用');
        app.$emit('reduce');
    }
    

    面试官问:你知道自定义指令吗

    达达回答:知道吧

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue入门之自定义指令</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <div v-test="color">
            {{num}}
        </div>
    </div>
    <button οnclick="unbindApp()">解绑</button>
    
    
    <script type="text/javascript">
    function unbindApp() {
        app.$destroy();
    }
    
    
    // 自定义指令
    Vue.directive("test",{
        //被绑定
        bind:function (el, binding, vnode) {
            console.log("1-bind 被绑定");
            console.log("el:",el);
            console.log("binding:",binding);
            console.log("vnode:",vnode);
            el.style.color = binding.value;
        },
        //被插入
        inserted:function (el, binding, vnode) {
            console.log("2-inserted 被插入");
        },
        //更新
        update:function (el, binding, vnode) {
            console.log("3-update 更新");
        },
        //更新完成
        componentUpdated:function (el, binding, vnode) {
            console.log("4-componentUpdated 更新完成");
        },
        //解绑
        unbind:function (el, binding, vnode) {
            console.log("5-unbind 解绑");
        }
    });
    
    
    var app = new Vue({
        el:'#app',
        data:{
            num: 123,
            color:'red'
        }
    })
    </script>
    </body>
    </html>
    

    面试官问:你用过组件吗?

    达达回答,用过的

    组件全局注册

    Vue.component('button-counter', {
        data: function () {
            return {
                count: 0
            }
        },
        template: '<button v-on:click="count++">全局组件: {{ count }}</button>'
    });
    
    
    new Vue({
        el: '#app'
    });
    
    
    <button-counter></button-counter>
    

    组件局部注册

    new Vue({
        el: '#app',
        components:{
            "button-inner":{
                data: function() {
                    return {
                        inner: 0
                    }
                },
                template: '<button v-on:click="inner++">局部组件: {{ inner }}</button>'
            }
        }
    });
    
    
    <button-inner></button-inner>
    

    props属性传值

    new Vue({
            el: '#app',
            components:{
                "button-props":{
                    template:`
                    <div style="color:red;">
                    参数1: {{ da }}:---参数2: 
                    {{fromHere}}
                    </div>
                    `,
                    props:['da', 'fromHere']
                }
            }
        });
    
    
    // html使用
    <button-props da="da" from-here="world"></button-props>
    
    
    props中需要驼峰取值
    

    父子组件

    // 子组件
    var city = {
        template:`<div>dada</div>`
    }
    // 父组件
    var parent = {
        template:
            `<div>
                <p> dadada!</p>
                <city></city>
            </div>`,
        components:{
            "city": city
        }
    }
    
    
    // 实例化
    new Vue({
        el: '#app',
        // 定义局部组件
        components:{
            // 组件注册
            "parent": parent
        }
    });
    
    
    // html使用
    <parent></parent>
    

    面试官:你了解模板吗?

    达达回答:还好

    <div id="app">
    </div>
    
    
    <script type="text/javascript">
        // 实例化
        new Vue({
            el: '#app',
            data: {
                message: 'hello'
            },
            template:`<h1 style="color:red">模板</h1>`
        });
    </script>
    
    <div id="app">
        <template id="demo2">
            <h2 style="color:red">template模板</h2>
        </template>
    </div>
    
    
    <script type="text/javascript">
        // 实例化
        new Vue({
            el: '#app',
            data: {
                message: 'hello'
            },
            template:'#demo2'
        });
    </script>
    
    <div id="app">
    </div>
    
    
    <script type="x-template" id="demo3">
        <h2 style="color:red">script标签模板</h2>
    </script>
    
    
    <script type="text/javascript">
        // 实例化
        new Vue({
            el: '#app',
            data: {
                message: 'hello'
            },
            template:'#demo3'
        });
    </script>
    

    面试问:你了解插槽不?

    达达回答:插槽就是slot,是组件的一块Hmtl模板

    <div id="app">
        <children>
            <span>123</span>
        </children>
    </div>
    
    
    <script type="text/javascript">
        var app = new Vue({
            el: '#app',
            components: {
                children: {
                    template: "<button><slot></slot>单个插槽</button>"
                }
            }
        });
    </script>
    

    具名插槽slot,具名插槽可以在一个组件中出现n次

    <div id="app">
        <children>
            <span slot="first" @click="toknow">123</span>
            <span slot="second">456</span>
        </children>
    </div>
    
    
    <script type="text/javascript">
        var app = new Vue({
            el: '#app',
            methods: {
                toknow: function () {
                    console.log("dada");
                }
            },
            components: {
                children: {
                    template: "<button>
                    <slot name='first'>
                    </slot>
                    具名插槽
                    <slot name='second'>
                    </slot>
                    </button>"
                }
            }
        });
    </script>
    

    作用域插槽slot

    <div id="app">
        <!-- 将数据传递给组件 -->
        <tb-list :data="data">
            <template slot-scope="scope">
                <p>索引:{{JSON.stringify(scope)}}</p>
                <p>索引:{{scope.$index}}</p>
                <p>姓名:{{scope.row.name}}</p>
                <p>年龄: {{scope.row.age}}</p>
                <p>性别: {{scope.row.sex}}</p>
            </template>
        </tb-list>
    </div>
    
    
    <script type="text/javascript">
        var app = new Vue({
            el: '#app',
            data: {
                data: [{
                    name: 'dada',
                    age: '12',
                    sex: 'man'
                }]
            },
            components: {
                // 作用域slot
                'tb-list': {
                    template:
                        `<ul>
                            <li v-for="(item, index) in data">
                                <slot :row="item" :$index="index">
                                </slot>
                            </li>
                        </ul>`,
                    // 获取值
                    props: ['data']
                }
            }
        });
    </script>
    

    面试官问:你用过vue-cli吗?说一说

    达达回答:好的

    vue-cli安装,第一用npm安装

    npm -v
    

    vue-cli安装

    npm install vue-cli -g
    
    vue -V
    
    
    -g代表全局安装,然后查看版本
    

    初始化项目

    用vue init命令来初始化项目
    
    
    vue init <template-name> <project-name>
    
    
    init:表示要用vue-cli来初始化项目
    
    
    <template-name>:表示模板名称
    
    
    vue-cli官方提供的5种模板
    
    
    webpack
    
    
    webpack-simple
    
    
    browserify
    
    
    browserify-simple
    
    
    simple
    
    
    <project-name>:标识项目名称,用户根据自己的项目来起名字。
    

    项目初始化

    vue init webpack my-vue-demo
    
    Project name:项目名称
    
    
    Project description:项目描述
    
    
    Author:作者
    
    
    Install vue-router? 是否安装vue的路由插件,需要安装,选择Y
    
    
    Use ESLint to lint your code? 是否用ESLint来限制你的代码错误和风格。不需要输入n,需要选择y
    
    
    setup unit tests with Karma + Mocha? 是否需要安装单元测试工具
    
    
    Setup e2e tests with Nightwatch? 是否安装e2e来进行用户行为模拟测试
    

    运行项目

    npm run dev
    
    
    npm run build
    

    面试官问:你了解vue-router吗?说一说

    达达回答,嗯,了解。

    安装

    npm install vue-router --save
    

    核心文件

    import Vue from 'vue'
    import Router from 'vue-router'
    import HelloWorld from '@/components/HelloWorld'
    
    
    // Vue全局使用Router
    Vue.use(Router)
    
    
    export default new Router({
      routes: [                //配置路由,这里是个数组
        {                        //每一个链接都是一个对象
          path: '/',            //链接路径
          name: 'HelloWorld',        //路由名称,
          component: HelloWorld     //对应的组件模板
        }
      ]
    })
    

    使用

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    
    Vue.config.productionTip = false
    
    
    new Vue({
      el: '#app',
      router, // 注入框架中
      components: { App },
      template: '<App/>'
    })
    

    页面跳转

    <router-link to="/">[显示字段]</router-link>
    
    
    <p>导航 :
       <router-link to="/">首页</router-link>
       <router-link to="/hello">hello</router-link>
    </p>
    

    编程式导航

    this.$router.push('/xxx')
    
    
    <button @click="goHome">回到首页</button>
    
    
    export default {
        name: 'app',
        methods: {
            goHome(){
                this.$router.push('/home');
            }
        }
    }
    
    
    //  同于 history.back()
    this.$router.go(-1)
    // 同于 history.forward()
    this.$router.go(1)
    

    路由嵌套

    <template>
        <div class="hello">
            <h1>{{ msg }}</h1>
     
            <p>导航 :
                <router-link to="/home">首页</router-link> | 
                <router-link to="/home/one">-子页面1</router-link> |
                <router-link to="/home/two">-子页面2</router-link>
            </p>
    
    
            <router-view/>
        </div>
    </template>
    
    
    <script>
    export default {
        name: 'Home',
        data () {
            return {
                msg: 'dada!'
            }
        }
    }
    </script>
    
    
    <style scoped>
    </style>
    

    子页面

    <template>
        <div class="hello">
            <h1>{{ msg }}</h1>
        </div>
    </template>
    <script>
    export default {
        name: 'One',
        data () {
            return {
                msg: 'Hi, I am One Page!'
            }
        }
    }
    </script>
    
    
    <style scoped>
    </style>
    
    
    <template>
        <div class="hello">
            <h1>{{ msg }}</h1>
        </div>
    </template>
    <script>
    export default {
        name: 'Two',
        data () {
            return {
                msg: 'Hi, I am Two Page!'
            }
        }
    }
    </script>
    
    
    <style scoped>
    </style>
    

    路由配置

    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from '@/components/Home'
    import One from '@/components/One' 
    import Two from '@/components/Two'
    
    
    Vue.use(Router)
    
    
    export default new Router({
        routes: [
        {
            path: '/', // 默认页面重定向到主页
            redirect: '/home'
        },
        {
            path: '/home', // 主页路由
            name: 'Home',
            component: Home,
            children:[ // 嵌套子路由
                {
                    path:'one', // 子页面1
                    component:One
                },
                {
                    path:'two', // 子页面2
                    component:Two
                },
            ]
        }
        ]
    })
    

    路由传递参数

    <router-link :to="{name:xxx, params: {key:value}}">
    dada
    </router-link>
    
    <router-link :to="{name: 'one', params:{username:'123'}}">
    子页面
    </router-link>
    
    {
        path:'one', // 子页面
        name: 'one', // 路由名称-命名路由
        component:One
    }
    
    <h2>{{$route.params.username}}</h2>
    

    url中传递参数

    {
        path:'/home/two/:id/:name', // 子页面
        component:Two
    },
    
    <p>ID:{{ $route.params.id}}</p>
    <p>名称:{{ $route.params.name}}</p>
    
    <router-link to="/home/two/1/达达">子页面</router-link>
    

    编程式导航带参数

    {
        path:'/home/three', // 子页面
        name: 'three',
        component:Three
    }
    
    <p>ID:{{ $route.params.id}}</p>
    <p>名称:{{ $route.params.name}}</p>
    
    <button @click="toThreePage">页面-params传参</button>
    
    
    // script
    methods: {
        toThreePage() {
            this.$router.push(
            {
            name: 'three', 
            params: {
            id: 1, 
            name: 'dada'
            }
            }
            )
        }
    }
    

    query传参数

    {
        path:'/home/three', // 子页面
        name: 'three',
        component:Three
    }
    
    <p>ID:{{ $route.query.id}}</p>
    <p>名称:{{ $route.query.name}}</p>
    
    <button @click="toThreePage">页面-params传参</button>
    
    
    methods: {
        toThreePage() {
            this.$router.push(
            {path: '/home/three', query: {id: 1, name: 'da'}}
            )
        }
    }
    

    命名路由

    {
        path: 'one', // 子页面
        name: 'one', // 路由名称-命名路由
        component: One // 页面组件
    }
    
    // template跳转调用
    <router-link :to="{name: 'one'}">子页面</router-link>
    
    
    // router.push函数跳转调用
    router.push({ name: 'user'}})
    
    import Vue from 'vue'
    import Router from 'vue-router'
    // 创建页面组件
    const Header = { template: '<div>Header</div>' }
    const Left = { template: '<div>Left</div>' }
    const Right = { template: '<div>Right</div>' }
    
    
    Vue.use(Router)
    
    
    export default new Router({
        routes: [
        {
            path: '/', // 主页路由
            components: {
                default: Header,
                a: Left,
                b: Right
            }
        }
        ]
    })
    
    
    <template>
        <div id="app">
            <router-view />
            <router-view name="a" class="left" />
            <router-view name="b" class="right" />
        </div>
    </template>
    
    
    <script>
    export default {
        name: 'App'
    }
    </script>
    
    
    <style>
    #app {
        text-align: center;
        color: #2c3e50;
         500px;
        border: 1px solid red;
        margin: 0 auto;
    }
    
    
    .left,.right{
        float: left;
        48%;
        text-align: center;
        border:1px solid red
    }
    </style>
    

    重定向

    export default new Router({
        routes: [
        {
            path: '/', // 默认页面重定向到主页
            redirect: '/home' // 重定向
        },
        {
            path: '/home', // 主页路由
            component: Home,
            children:[ // 嵌套子路由
                {
                    path:'/home/two/:id/:name', // 子页面
                    component:Two
                },
                {
                    path:'/home/three/:id/:name', // 子页面
                    name: 'three', // 路由名称-命名路由
                    redirect: '/home/two/:id/:name' // 重定向-传递参数
                },
            ]
        }
        ]
    })
    
    <router-link to="/">首页</router-link> | 
    <router-link to="/home/two/1/lisi">子页面</router-link>  |
    <router-link :to="{name: 'three', params: {id: 1, name: 'dada'}}">
    子页面
    </router-link>
    
    redirect: '/home' // 重定向-不带参数
    
    redirect: '/home/two/:id/:name' // 重定向-传递参数
    

    别名

    {
        path:'/one', // 子页面
        component:One,
        alias: '/oneother'
    }
    
    <router-link to="/oneother">子页面1</router-link>
    

    过渡动画

    <transition name="fade" mode="out-in">
        <router-view />
    </transition>
    

    .fade-enter-active {
        transition: opacity .5s;
    }
    
    
    .fade-enter {
        opacity: 0;
    }
    
    
    .fade-leave {
        opacity: 1;
    }
    
    
    .fade-leave-active {
        opacity:0;
        transition: opacity .5s;
    }
    

    mode模式

    export default new Router({
        mode: 'history', //mode模式
        routes: [...]
    })
    

    404

    // 404
    {
        path: '*',
        component: () => import('@/components/404')
    }
    

    路由钩子,第一全局钩子,第二,路由单独钩子,第三,组件内钩子

    const router = new VueRouter({ ... })
    
    
    // 全局路由拦截-进入页面前执行
    router.beforeEach((to, from, next) => {
        next();
    });
    
    
    router.afterEach(() => {
     
    });
    
    
    export default router;
    

    路由单独钩子

    {
        path:'/home/one', // 子页面
            component: One,
       
            beforeEnter: (to, from, next) => {
            console.log('进入前执行');
                next();
            }
    }
    

    组件内钩子

    <script>
    export default {
        name: 'Two',
        data () {
            return {
                msg: 'dada'
            }
        },
    
    
        beforeRouteEnter(to, from, next) {
            console.log('进入enter路由钩子')
            next()
        },
    
    
        beforeRouteLeave(to,from, next){
            console.log('进入leave路由钩子')
            next()
        },
    
    
        beforeRouteUpdate(to, from, next) {
            console.log('进入update路由钩子')
            console.log(to.params.id)
            next()
        }
    }
    </script>
    

    路由

    import Home from '@/components/Home'
    {
            path: '/home',
            component: Home
    }
    

    面试官问:你了解vuex是什么吗?要不也说说

    达达回答:好的。

    vuex是一个为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,以相应的规则保证状态以一种可预测的方式发生变化。

    单向数据流

    vuex的核心

    安装

    npm install vuex --save
    

    使用

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    const state = {
        count: 1
    }
    const mutations = {
        DA(state, n) {
            state.count += n;
        }
    }
    const getters = {
        count: function(state){
            return state.count;
        }
    }
    const actions ={
        // 触发mutations中相应的方法-一般小写
        add ({commit}, data) {
            commit('DA', data)
        }
    }
    
    
    const store = new Vuex.Store({
        state,
        mutations,
        getters,
        actions
    });
    
    
    export default store;
    
    <h2>{{ $store.state.count }}</h2>
    
    computed: {
        count() {
            return this.$store.state.count;
        }
    }
    
    computed: mapState({
        // es5写法
        count: function (state) {
             return state.count;
         },
        // es6写法
        count: state => state.count
    })
    
    数组获取
    computed: mapState(['count'])
    
    computed: mapState({
        count: 'count'
    })
    
    <button @click="$store.commit('DA')">+</button>
    const mutations = {
        // 状态变更函数
        DA(state) {
            state.count++;
        }
    }
    

    每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块,从上至下进行同样方式的分割。

    // 模块A
    const moduleA = {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    
    // 模块B
    const moduleB = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    
    
    // 组装
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    
    // 取值
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
    

    面试官最后一问:你了解axios吗?

    达达回答:嗯,用过。

    Axios 是基于 promise 的 HTTP 库,用在浏览器和 node.js 中。就是前端最火最简单的一个http请求解决方案。

    安装

    npm install vuex --save
    

    代码封装

    import fetch from '@/util/fetch'
    const TMPURL = ''; // url地址
    const params = {}; // 参数
    fetch.post(TMPURL + '/login/login', params);
    
    import axios from 'axios';
    const httpService = axios.create({
        baseURL: process.env.BASE_API, // 需自定义
        // 请求超时时间
        timeout: 3000 
    });
    
    
    // request拦截器
    httpService.interceptors.request.use(
        config => {
            // 加入token
            if (true) { 
                config.headers['User-Token'] = '';
            }
            return config;
        }, 
        error => 
            Promise.reject(error);
        }
    )
    
    
    // respone拦截器
    httpService.interceptors.response.use(
        response => {
            const res = response.data;
            if (res.statuscode != 1) {
                return Promise.reject({
                    status: res.statuscode,
                    message: res.message
                });
            } else {
                return response.data;
            }
        },
    
    
        error => {
             if (error && error.response) {
                switch (error.response.status) {
                    case 400:
                        error.message = '错误请求';
                        break;
                    case 401:
                        error.message = '未授权,请重新登录';
                        break;
                    case 403:
                        error.message = '拒绝访问';
                        break;
                    case 404:
                        error.message = '请求错误,未找到该资源';
                        break;
                    case 405:
                        error.message = '请求方法未允许';
                        break;
                    case 408:
                        error.message = '请求超时';
                        break;
                    case 500:
                        error.message = '服务器端出错';
                        break;
                    case 501:
                        error.message = '网络未实现';
                        break;
                    case 502:
                        error.message = '网络错误';
                        break;
                    case 503:
                        error.message = '服务不可用';
                        break;
                    case 504:
                        error.message = '网络超时';
                        break;
                    case 505:
                        error.message = 'http版本不支持该请求';
                        break;
                    default:
                        error.message = `未知错误${error.response.status}`;
                }
            } else {
                error.message = "连接到服务器失败";
            }
            return Promise.reject(error);
        }
    )
    /*
     *  get请求
     *  url:请求地址
     *  params:参数
     * */
    export function get(url, params = {}) {
        return new Promise((resolve, reject) => {
            httpService({
                url: url,
                method: 'get',
                params: params
            }).then(response => {
                resolve(response);
            }).catch(error => {
                reject(error);
            });
        });
    }
    
    
    /*
     *  post请求
     *  url:请求地址
     *  params:参数
     * */
    export function post(url, params = {}) {
        return new Promise((resolve, reject) => {
            httpService({
                url: url,
                method: 'post',
                data: params
            }).then(response => {
                resolve(response);
            }).catch(error => {
                reject(error);
            });
        });
    }
    
    
    /*
     *  文件上传
     *  url:请求地址
     *  params:参数
     * */
    export function fileUpload(url, params = {}) {
        return new Promise((resolve, reject) => {
            httpService({
                url: url,
                method: 'post',
                data: params,
                headers: { 'Content-Type': 'multipart/form-data' }
            }).then(response => {
                resolve(response);
            }).catch(error => {
                reject(error);
            });
        });
    }
    
    
    export default {
        get,
        post,
        fileUpload
    }
    

    推荐系列

    推荐阅读  点击标题可跳转

    【面试Vue全家桶】vue前端交互模式-es7的语法结构?async/await

    【面试需要-Vue全家桶】一文带你看透Vue前端路由

    【面试需要】掌握JavaScript中的this,call,apply的原理

    2019年的每一天日更只为等待她的出现,好好过余生,庆余年 | 掘金年度征文

    进来就是一家人【达达前端技术社群⑥】

    觉得本文对你有帮助?请分享给更多人

    关注「达达前端」加星标,提升前端技能

    在博客平台里,未来的路还很长,也希望自己以后的文章大家能多多支持,多多批评指正,我们一起进步,一起走花路。

    非常感谢读者能看到这里,如果这个文章写得还不错,觉得「达达」我有点东西的话,觉得我能够坚持的学习,觉得此人可以交朋友的话, 求点赞,求关注,求分享,对暖男我来说真的

    非常有用!

    感谢阅读,原创不易,喜欢就点个[在看] or [转发朋友圈],这是我写作最大的动力。

    意见反馈

    若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。

    这是一个有质量,有态度的公众号

    点关注,有好运

    好文章,我在看❤️

  • 相关阅读:
    8086汇编--1--通用寄存器和简单汇编指令
    写在前面的吐槽!
    汇编/Debug学习计划
    开篇-引文
    看懂别人的代码,和自己能写代码是两回事
    内存管理
    Flink基本原理及应用场景
    IDEA Maven Dependencies标红报错
    Spark Streaming流式处理
    Kafka
  • 原文地址:https://www.cnblogs.com/dashucoding/p/12633848.html
Copyright © 2011-2022 走看看