• vue面试(一)


    1.watch如何深度监听,watch监听引用类型数据,拿不到oldVal

    <template>
        <div>
            <input v-model="name"/>
            <input v-model="info.city"/>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                name: '双越',
                info: {
                    city: '北京'
                }
            }
        },
        watch: {
            name(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
            },
            info: {
                handler(oldVal, val) {
                    // eslint-disable-next-line
                    console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
                },
                deep: true // 深度监听,可以监听到引用类型中的属性city。
            }
        }
    }
    </script>

    2. v-if和v-show

    跟新不是很频繁,用v-if,

    跟新很频繁,用v-show,利用的display:none

    3,v-for 循环遍历,key的重要性,v-for 和v-if是不能一起使用

    加了key(一定要具有唯一性),vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM

    <template>
        <div>
            <p>遍历数组</p>
            <ul>
                <li v-for="(item, index) in listArr" :key="item.id">
                    {{index}} - {{item.id}} - {{item.title}}
                </li>
            </ul>
    
            <p>遍历对象</p>
            
            <ul  v-if="flag">
                <!-- v-if不能和v-for在同一个标签使用,v-for渲染模板的优先级比v-if高,遍历一遍v-if判断一次,效率不高,在
                在父级容器加个v-if判断即可
                 -->
                <li v-for="(val, key, index) in listObj" :key="key">
                    {{index}} - {{key}} -  {{val.title}}
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                
                flag: false,
                listArr: [
                    { id: 'a', title: '标题1' }, // 数据结构中,最好有 id ,方便使用 key
                    { id: 'b', title: '标题2' },
                    { id: 'c', title: '标题3' }
                ],
                listObj: {
                    a: { title: '标题1' },
                    b: { title: '标题2' },
                    c: { title: '标题3' },
                }
            }
        }
    }
    </script>

    4. 事件, event, 事件修饰符, 事件绑定到哪里 

     在Vue中,事件修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。在Vue中事件修饰符主要有:
    
    .stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡
    .prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
    .capture:与事件冒泡的方向相反,事件捕获由外到内
    .self:只会触发自己范围内的事件,不包含子元素
    .once:只会触发一次

     

    <template>
        <div>
            <p>{{num}}</p>
            <button @click="increment1">+1</button>
            <button @click="increment2(2, $event)">+2</button>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                num: 0
            }
        },
        methods: {
            increment1(event) {
               
                console.log('event', event, event.__proto__.constructor) // 是原生的 event 对象
          
                //event.target 事件挂载到那个节点上
                console.log(event.target)
           
                console.log(event.currentTarget) // 注意,事件是被注册到当前元素的,和 React 不一样
                this.num++
    
                // 1. event 是原生的
                // 2. 事件被挂载到当前元素
                // 和 DOM 事件一样
            },
            increment2(val, event) {
                // eslint-disable-next-line
                console.log(event.target)
                this.num = this.num + val
            },
            loadHandler() {
                // do some thing
            }
        },
        mounted() {
            window.addEventListener('load', this.loadHandler)
        },
        beforeDestroy() {
            //【注意】用 vue 绑定的事件,组建销毁时会自动被解绑
            // 自己绑定的事件,需要自己销毁!!!
            window.removeEventListener('load', this.loadHandler)
        }
    }
    </script>

    5. v-model,常见表单项, textarear checkbox, radio, select,

    修饰符, lazy number trim

    <template>
        <div>
            <p>输入框: {{name}}</p>
            <!-- 修饰符trim,清除前后空格 -->
            <input type="text" v-model.trim="name"/>
            <!-- 修饰符lazy,只有在input输入框发生一个blur时才触发 -->
            <input type="text" v-model.lazy="name"/>
            <!-- 修饰符number, 将用户输入的字符串转换成number -->
            <input type="text" v-model.number="age"/>
    
            <p>多行文本: {{desc}}</p>
            <textarea v-model="desc"></textarea>
            <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->
    
            <p>复选框 {{checked}}</p>
            <input type="checkbox" v-model="checked"/>
    
            <p>多个复选框 {{checkedNames}}</p>
            <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
            <label for="jack">Jack</label>
            <input type="checkbox" id="john" value="John" v-model="checkedNames">
            <label for="john">John</label>
            <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
            <label for="mike">Mike</label>
    
            <p>单选 {{gender}}</p>
            <input type="radio" id="male" value="male" v-model="gender"/>
            <label for="male">男</label>
            <input type="radio" id="female" value="female" v-model="gender"/>
            <label for="female">女</label>
    
            <p>下拉列表选择 {{selected}}</p>
            <select v-model="selected">
                <option disabled value="">请选择</option>
                <option>A</option>
                <option>B</option>
                <option>C</option>
            </select>
    
            <p>下拉列表选择(多选) {{selectedList}}</p>
            <select v-model="selectedList" multiple>
                <option disabled value="">请选择</option>
                <option>A</option>
                <option>B</option>
                <option>C</option>
            </select>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                name: '双越',
                age: 18,
                desc: '自我介绍',
    
                checked: true,
                checkedNames: [],
    
                gender: 'male',
    
                selected: '',
                selectedList: []
            }
        }
    }
    </script>

    6.props, $emit, 组件通讯,自定义事件

    父子传递,自定义事件

    Vue兄弟组件之间通信 eventBus

    新建event.js,兄弟组件映入该组件,兄弟组件通过event.$on, 或者event.$emit来通信

    import Vue from 'vue'
    
    export default new Vue()

    或者在main.js中设置全局事件总线,然后兄弟组件this.$bus.$on,  this.$bus.$emit来通信

    // new Vue()实例化了一个Vue的实例化对象
    //因为只有组件对象或者Vue的实例化对象才能调用$on和$emit
    
    //想要成为事件总线的条件:
    //1、所有的组件对象必须都能看得到这个总线对象,因此我们把这个对象放在了Vue原型
    //2、这个事件总线对象必须能调用$on和$emit方法(总线对象必须是Vue的实例化对象或者是组件对象)
    
    
    new Vue({
      beforeCreate(){
        Vue.prototype.$bus = this
      },
      el:'#root',
      render: h => h(App)
    })

    父组件

    <template>
        <div>
            <Input @add="addHandler"/>
            <List :list="list" @delete="deleteHandler"/>
        </div>
    </template>
    
    <script>
    import Input from './Input'
    import List from './List'
    
    export default {
        components: {
            Input,
            List
        },
        data() {
            return {
                list: [
                    {
                        id: 'id-1',
                        title: '标题1'
                    },
                    {
                        id: 'id-2',
                        title: '标题2'
                    }
                ]
            }
        },
        methods: {
            addHandler(title) {
                this.list.push({
                    id: `id-${Date.now()}`,
                    title
                })
            },
            deleteHandler(id) {
                this.list = this.list.filter(item => item.id !== id)
            }
        },
        created() {
            // eslint-disable-next-line
            console.log('index created')
        },
        mounted() {
            // eslint-disable-next-line
            console.log('index mounted')
        },
        beforeUpdate() {
            // eslint-disable-next-line
            console.log('index before update')
        },
        updated() {
            // eslint-disable-next-line
            console.log('index updated')
        },
    }
    </script>

    子组件input

    <template>
        <div>
            <input type="text" v-model="title"/>
            <button @click="addTitle">add</button>
        </div>
    </template>
    
    <script>
    import event from './event'
    
    export default {
        data() {
            return {
                title: ''
            }
        },
        methods: {
            addTitle() {
                // 调用父组件的事件
                this.$emit('add', this.title)
    
                // 调用自定义事件
                event.$emit('onAddTitle', this.title)
    
                this.title = ''
            }
        }
    }
    </script>

    子组件List

    <template>
        <div>
            <ul>
                <li v-for="item in list" :key="item.id">
                    {{item.title}}
    
                    <button @click="deleteItem(item.id)">删除</button>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    import event from './event'
    
    export default {
        // props: ['list']
        props: {
            // prop 类型和默认值
            list: {
                type: Array,
                default() {
                    return []
                }
            }
        },
        data() {
            return {
    
            }
        },
        methods: {
            deleteItem(id) {
                this.$emit('delete', id)
            },
            addTitleHandler(title) {
                // eslint-disable-next-line
                console.log('on add title', title)
            }
        },
        created() {
            // eslint-disable-next-line
            console.log('list created')
        },
        mounted() {
            // eslint-disable-next-line
            console.log('list mounted')
    
            // 绑定自定义事件
            event.$on('onAddTitle', this.addTitleHandler)
        },
        beforeUpdate() {
            // eslint-disable-next-line
            console.log('list before update')
        },
        updated() {
            // eslint-disable-next-line
            console.log('list updated')
        },
        beforeDestroy() {
            // 及时销毁,否则可能造成内存泄露
            event.$off('onAddTitle', this.addTitleHandler)
        }
    }
    </script>

     父子组件生命周期的顺序, 父组件created创建了实例,子组件list也创建了实例,并且mounted渲染了模板,然后父组件才mounted渲染模板

    子组件更新完,父组件才会更新完

    生命周期过程;https://www.cnblogs.com/fsg6/p/14468597.html

  • 相关阅读:
    Go从入门到精通——Go语言中程序文件的组织方法
    Go从入门到精通——怎样查看 Go 语言的文档
    AU篇——处理人声混BGM_(尽可能)去BGM提取人声
    【漏洞分析】DDOS攻防分析(一)——DNS篇
    【网络安全设备系列】15、安全网关/统一威胁管理(UTM)
    【网络安全设备系列】14、堡垒机
    【网络安全设备系列】13、网页防篡改
    【网络安全设备系列】12、态势感知
    【网络安全设备系列】11、抗DDOS设备
    【网络安全设备系列】10、安全审计系统
  • 原文地址:https://www.cnblogs.com/fsg6/p/14468294.html
Copyright © 2020-2023  润新知