Vue面试(3)-- vue高级特性

常考的vue高级特性(知识点简记)

1. 自定义v-model

<template>
    <div>
        <p>vue 高级特性</p>
        <hr>
        <!-- 自定义 v-model -->
        <p>{{name}}</p>
        <CustomVModel v-model="name"/>
        <MixinDemo/>
    </div>
</template>
<script>
 export default {
    components: {
        CustomVModel
    },
    data() {
        return {
            name: 'name'
        }
    }
}
</script>

颜色选择器 双向数据绑定

customVModel.vue

<template>
    <!-- 例如:vue 颜色选择 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)">
    <!--
        1. 上面的 input 使用了 :value 而不是 v-model
        2. 上面的 change1 和 model.event1 要对应起来
        3. text1 属性对应起来
    -->
</template>

<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>

2. $nextTick

  vue是异步渲染,

  data改变之后,DOM不会立刻渲染,

  $nextTick会在DOM渲染之后被触发,以获得最新的DOM节点

<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">添加一项</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    addItem() {
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        // 1. 异步渲染,$nextTick 待 DOM 渲染完再回调
        // 2. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次(使用一次$nextTick)
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
</script>

(在DOM元素定义ref=ul1,之后可以使用this.$refs.ul1拿到DOM元素)

不使用$nextTick的效果: 点击一次输出3,点击第二次输出6

为了使点击之后可以立刻得到渲染结果:使用$nextTick

3. slot插槽

  组件插槽的作用:父组件向子组件传递内容(模板的内容)

  插槽的位置:位于子组件的模板中

(1) 基本使用

<template>
    <div>
        <p>vue 高级特性</p>
        <!-- slot -->
        <SlotDemo :url="website.url">
            {{website.title}}
        </SlotDemo>
    </div>
</template>

<script>
import SlotDemo from './SlotDemo'
export default {
    components: {
        SlotDemo
    },
    data() {
        return {
            name: '姓名',
            website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            }
        }
    }
}
</script>

SlotDemo.vue

<template>
    <a :href="url">
        <slot>
            显示默认内容,即父组件没设置内容时
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {}
    }
}
</script>

(效果:链接会以标签形式显示并且显示title内容)

(2)作用域插槽

<template>
    <a :href="url">
        <slot :slotData="website">
            {{website.subTitle}} <!-- 父组件不传内容时默认值显示 subTitle  -->
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '轻量级富文本编辑器'
            }
        }
    }
}
</script>

(如果不传入值{{website.subTitle}}},则会显示子组件的默认subtitle)

使用:子组件中作用域的data让父组件可以获取到

<ScopedSlotDemo :url="website.url">
            <template v-slot="slotProps">
                {{slotProps.slotData.title}}
            </template>
 </ScopedSlotDemo>

效果:页面显示子组件内容wangEditor

(思路:在slot中定义动态属性slotData,然后把他定义到website上,website中含有title和subtitle。然后在index中使用ScopedSlotDemo中定义v-slot=slotProps.之后可以使用slot Props.slot DaTa拿到ScopedSlotDemo组件中website的内容,从而可以拿到website的title)

(3)具名插槽

有名字的插槽---根据内容进行匹配--没有名称会默认匹配

父组件往子组件传递内容的时候需要对应好名字

4. 动态组件异步组件

(1)动态组件

  用法: :is=component-name

  需要根据数据、动态渲染的场景。即组件类型并不确定。(一般情况下组件类型是确定的)

举例使用场景:新闻详情页。(组件位置不确定或者种类不确定。即不知道要渲染甚么样的组件,只知道数据。需要根据数据确定组件的类型,这时就需要用到动态组件)

<template>
    <div>
        <p>vue 高级特性</p>
        <!-- 动态组件 -->
        <!-- <component :is="NextTickName"/> -->
        <div v-for="(index, value) in newsData" :key="index">
            <component :is="value.type"></component>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: 'name',
             // NextTickName: "NextTick",
            newsData: {
                1: {type: 'text'},
                2: {type: 'text'},
                3: {type: 'image'},
            }
        }
    }
}
</script>

(根据获取到的组件(text,image)进行渲染)

(2)异步组件

  Import函数

  按需加载、异步加载大组件

(什么时候用就什么时候加载,如果不使用永远都不会加载,适合于组件比较大比较复杂,这样会优化性能)

使用语句import SlotDemo from './SlotDemo' 是同步加载

<!-- 异步组件 -->
        <FormDemo v-if="showFormDemo"/>
        <button @click="showFormDemo = true">show form demo</button> 

// 然后在components里面写
components: {
       FormDemo: () => import('../BaseUse/FormDemo'),
    }

效果:没有点击时不会加载FormDemo,点击之后会加载然后渲染出来

5.keep-alive

  缓存组件

  频繁切换,不需要重复渲染

  Vue常见性能优化

KeepAlive.Vue中引入三个组件KeepAliveAtageA、KeepAliveAtageB、KeepAliveAtageC是三个按钮

依次点击BC的效果:

不使用keep alive

使用keepalive

A mounted

A destroyed

B mounted

B destroyed

C mounted

C destroyed

A mounted

A created

B created

C created

<KeepAliveStageA v-if="state === 'A'"/> 

<KeepAliveStageB v-if="state === 'B'"/>

<KeepAliveStageC v-if="state === 'C'"/>

 

<keep-alive> <!-- tab 切换 -->

            <KeepAliveStageA v-if="state === 'A'"/>

            <KeepAliveStageB v-if="state === 'B'"/>

            <KeepAliveStageC v-if="state === 'C'"/>

 </keep-alive>

使用keep-alive和v-show的区别:

v-show是通过原生CSS控制(使用情况:标签比较简单)

Keepalive 是在vue框架层级进行的JS对象的渲染(使用情况:带有层级或者tab切换的复杂组件切换)

<template>
    <div>
        <button @click="changeState('A')">A</button>
        <button @click="changeState('B')">B</button>
        <button @click="changeState('C')">C</button>

        <keep-alive> <!-- tab 切换 -->
            <KeepAliveStageA v-if="state === 'A'"/> <!-- v-show -->
            <KeepAliveStageB v-if="state === 'B'"/>
            <KeepAliveStageC v-if="state === 'C'"/>
        </keep-alive>
    </div>
</template>

<script>
import KeepAliveStageA from './KeepAliveStateA'
import KeepAliveStageB from './KeepAliveStateB'
import KeepAliveStageC from './KeepAliveStateC'

export default {
    components: {
        KeepAliveStageA,
        KeepAliveStageB,
        KeepAliveStageC
    },
    data() {
        return {
            state: 'A'
        }
    },
    methods: {
        changeState(state) {
            this.state = state
        }
    }
}
</script>

keepAliveStateA.vue

<template>
    <p>state A</p>
</template>

<script>
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('A mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('A destroyed')
    }
}
</script>

6. mixin

  多个组件有相同的逻辑,从中抽离出来

  Mixin并不是完美的解决方案,会有问题

  Vue 3提出的composition API 旨在解决这些问题

(Mixin就是一段js代码)

Mixin的问题

(1) 变量来源不明,不利于阅读

(2) 多个mixin可能会造成命名冲突

(3) Mixin和组件可能会出现多对多的关系,复杂度较高

<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">显示姓名</button>
    </div>
</template>

<script>
import myMixin from './mixin'

export default {
    mixins: [myMixin], // 可以添加多个,会自动合并起来
    data() {
        return {
            name: 'zs',
            major: 'web'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}
</script>

mixin.js

export default {
    data() {
        return {
            city: '北京'
        }
    },
    methods: {
        showName() {
            // eslint-disable-next-line
            console.log(this.name)
        }
    },
    mounted() {
        // eslint-disable-next-line
        console.log('mixin mounted', this.name)
    }
}
发布了26 篇原创文章 · 获赞 6 · 访问量 1393

猜你喜欢

转载自blog.csdn.net/Sabrina_cc/article/details/105366601
今日推荐