Vue学习Vue高级特性

Posted 周兴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue学习Vue高级特性相关的知识,希望对你有一定的参考价值。

1. 自定义v-model

Vue中的自定义v-model指的是在自定义组件中使用v-model语法糖来实现双向绑定。在Vue中,通过v-model指令可以将表单元素的值与组件实例的数据进行双向绑定。但是对于自定义组件,如果要实现v-model的双向绑定,就需要自定义v-model的实现方式。

自定义v-model需要在自定义组件中提供一个value属性和一个input事件,并在组件模板中使用v-bindvalue属性(text1)绑定到input元素的value属性上,并通过v-on监听input事件,当input事件触发时将输入框的值通过$emit方法发送出去。这样就可以在父组件中使用v-model语法糖来实现自定义组件的双向绑定了。

下面是一个自定义组件v-model的实例代码:

<!-- ChildComponent.vue -->
<template>
  <div>
    <input :value="text1" @input="$emit('change1', $event.target.value)">
  </div>
</template>

<script>
  export default 
  	model: 
		prop: 'text1',
		event: 'change1'
	,
    props: 
		text1 : String,
		default()
			return ''
		
	,
    // ...
  
</script>

在父组件中使用该组件,并使用v-model语法糖实现双向数据绑定:

<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component v-model="message"></child-component>
    <p>Message:  message </p>
  </div>
</template>

<script>
  import ChildComponent from './ChildComponent.vue';

  export default 
    components:  ChildComponent ,
    data() 
      return 
        message: ''
      
    
  
</script>

2. $nextTick

在Vue中,$nextTick是一个实例方法,它用于在DOM更新完成后执行一些操作,例如修改DOM、操作DOM元素等。它的作用是将回调函数延迟到下次DOM更新循环之后执行,从而确保在回调函数执行时,DOM已经被更新了。

$nextTick会将回调函数放入一个队列中,在下次DOM更新循环时执行该队列中的所有回调函数。这个过程可以确保在回调函数执行时,DOM已经被更新,因此可以进行一些操作,例如获取更新后的DOM节点、修改DOM属性等。

下面是一个使用$nextTick方法,获取组件data更新后的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()`)

        this.$nextTick(() => 
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        )
    
  

</script>

每点击’添加一项‘按钮后,会更新List数组,在数组中新添加3个元素,并打印出DOM元素的长度。如果不使用$nextTick方法,那么在第一次点击后打印的数字为3,然而DOM元素实际长度已经变为6了。下面是使用$nextTick方法的效果图,在第一次点击按钮后,打印的数字就是6。

3. slot 插槽

  • 基本使用
    使用插槽的目的是父组件需要向子组件中插入一段内容。
<!-- 父组件 -->
<template>
    <div>
        <p>vue 高级特性</p>
        <hr>
		<!-- 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>
<!-- 子组件 -->
<template>
    <a :href="url">
        <slot>
            默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>

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

</script>

  • 作用域插槽 ScopedSlot
    父组件希望使用子组件中的data数据作为插槽中的内容,可以使用作用域插槽。
<!-- 父组件 -->
<template>
    <div>
        <p>vue 高级特性</p>
        <hr>
        <!-- 作用域插槽写法 -->
        <ScopedSlotDemo :url="website.url">
            <template v-slot="slotProps">
                slotProps.slotData.title
            </template>
        </ScopedSlotDemo>
        
    </div>
</template>

<script>
import ScopedSlotDemo from './ScopedSlotDemo'

export default 
    components: 
        ScopedSlotDemo,
    ,
    data() 
        return 
            name: '双越',
            website: 
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            ,
        
    

</script>
<!-- 子组件 -->
<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>

  • 具名插槽

Vue中的具名插槽是指可以在一个组件中定义多个插槽,并使用不同的名称来标识它们的用途。相对于默认插槽,具名插槽可以更灵活地定制组件的样式和行为。

具名插槽可以在组件内部使用<slot>标签进行定义,同时可以通过在<slot>标签上添加name属性来指定插槽的名称。如果在组件的使用者中,需要为具名插槽提供自定义的内容,可以使用v-slot指令来绑定具名插槽。

4. Vue 动态组件

Vue动态组件是一种在运行时动态选择要渲染的组件的技术。它可以根据不同的条件渲染不同的组件,从而使应用程序更加灵活和可扩展。在Vue中,使用特殊的组件元素<component>来实现动态组件。<component>元素有一个is属性,它可以接受一个组件名或一个组件对象。当is属性的值发生变化时,<component>元素会销毁当前组件实例并创建一个新的组件实例。

  • 下面给出一个动态组件的使用场景:

假设我们有两个组件,一个是LoginForm,一个是SignupForm,它们分别表示登录和注册表单。我们希望根据用户点击的按钮来动态选择展示哪个表单。首先,需要在父组件中定义两个子组件,并设置一个变量currentForm来控制当前展示的组件,在这个父组件中,我们引入LoginFormSignupForm组件,并使用<component>元素动态渲染它们。这里currentForm变量初始值为空字符串,因此初始时不会渲染任何组件。当用户点击"登录"或“注册”按钮时,我们可以通过调用showLoginFormshowSignupForm方法来更新currentForm变量的值,从而动态渲染对应的表单组件。

<!--父组件-->
<template>
  <div>
    <button @click="showLoginForm">登录</button>
    <button @click="showSignupForm">注册</button>
    <component :is="currentForm"></component>
  </div>
</template>

<script>
import LoginForm from './LoginForm.vue'
import SignupForm from './SignupForm.vue'

export default 
  components: 
    LoginForm,
    SignupForm
  ,
  data() 
    return 
      currentForm: ''
    
  ,
  methods: 
    showLoginForm() 
      this.currentForm = 'LoginForm'
    ,
    showSignupForm() 
      this.currentForm = 'SignupForm'
    
  

</script>

我们需要在子组件中定义具体的表单。假设LoginFormSignupForm组件分别是以下形式:

<!--LoginForm.vue--> 
<template>
  <form>
    <input type="text" placeholder="用户名">
    <input type="password" placeholder="密码">
    <button type="submit">登录</button>
  </form>
</template>
<!--SignupForm.vue--> 
<template>
  <form>
    <input type="text" placeholder="用户名">
    <input type="password" placeholder="密码">
    <input type="password" placeholder="确认密码">
    <button type="submit">注册</button>
  </form>
</template>

5. Vue 异步组件

异步组件与常规组件的不同之处在于,异步组件只有在需要的时候才会被加载,而不是在应用初始化时就被全部加载。异步组件的应用场景是:当某个组件的体积比较大时,例如Echarts文件,如果应用初始化时就加载,会非常慢,严重影响性能。此时可以将该组件设置为异步组件,在需要使用该组件时,再加载该组件。异步组件通过import()函数引入。

以下代码中的FormDemo组件中包含多个表单,可以通过将其设置为异步组件,在需要的时候再将其加载。

<template>
    <div>
        <p>vue 高级特性:异步组件</p>
        <hr>
        <!-- 异步组件 -->
        <FormDemo v-if="showFormDemo"/>
        <button @click="showFormDemo = true">show form demo</button>
    </div>
</template>

<script>

export default 
    components: 
        FormDemo: () => import('./FormDemo'),   // 使用import函数,引入需要异步渲染的组件
    ,
    data() 
        return ,
		showFormDemo: false      // 首先将异步组件的 v-if 属性值设置为 false
    

</script>

6. 使用 keep-alive 缓存组件

keep-alive是Vue内置的一个组件,可以将其用于需要缓存的动态组件,避免每次重新渲染时都要执行组件的 created()mounted()destoryed()等钩子函数,从而提高组件的性能。

keep-alive 组件可以包裹动态组件,使其被缓存。被缓存的组件在组件切换时并不会被销毁,而是被保留在内存中,下次需要渲染时直接从缓存中读取组件实例,避免了组件的重新创建和重新渲染。

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

        <keep-alive>
            <KeepAliveStageA v-if="state === 'A'"/>
            <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>
<!--KeepAliveStageA组件-->
<template>
    <p>state A</p>
</template>

<script>
export default 
    mounted() 
        console.log('A mounted')
    ,
    destroyed() 
        console.log('A destroyed')
    

</script>
<!--KeepAliveStageB组件-->
<template>
    <p>state B</p>
</template>

<script>
export default 
    mounted() 
        console.log('B mounted')
    ,
    destroyed() 
        console.log('B destroyed')
    

</script>
<!--KeepAliveStageC组件-->
<template>
    <p>state C</p>
</template>

<script>
export default 
    mounted() 
        console.log('C mounted')
    ,
    destroyed() 

以上是关于Vue学习Vue高级特性的主要内容,如果未能解决你的问题,请参考以下文章

VUE.js高级

Vue.js学习(常用指令)

Vue.js学习笔记总结1

vue.js学习笔记

Vue.js 2.0 学习重点记录

Vue.js 2.0 学习重点记录