Vue 高级特性-基于 Vue2(笔记自用)

目录

1.自定义v-model

2.$nextTick

3.refs

4.slot

5.动态组件

6.异步组件

7.keep-alive

8.mixin


1.自定义v-model

vue中的v-model指令实现了表单的双向绑定

<input type="text" v-model="message">
<p>{{message}}</p>
// v-model只是语法糖,真正的实现形式:
<input type="text" :value="message" @input="message = $event.target.value">

一个组件上的v-model默认会利用名为value的prop和名为input的事件

例子:

// 父组件
<CustomVModel v-model="name"/>

// 子组件
<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 修改只会渲染一次
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
</script>

3.refs

  • ref 加在普通的元素上,用this.$refs.(ref值) 获取到的是dom元素
  • ref加在子组件上,用this.$refs.(ref值)获取到的是组件实例,可以使用组件的所有方法,例如 this.$refs.child.handleDelete()
  • 如果是v-for循环出来的ref,this.$refs.(ref值)获取到的是一个数组,循环处理即可

 注意:ref需要在dom渲染完成后才会有,所以只能在生命周期mounted()之后再调用,

            或是在this.$nextTick(()=>{}) 中调用

4.slot

插槽:父组件在子组件中插入一部分内容

slot-基本用法:

// 父组件
<SlotDemo :url="website.url"> {{website.title}} </SlotDemo>

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

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

slot-作用域插槽:父组件访问子组件属性值

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

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

slot-具名插槽

​
// 父组件
<NameSlot>
    <!--缩写<templete #header>-->
    <templete v-slot:header>
        <h1>将插入header slot中</h1>
    </templete>

    <p>将插入到 main slot 中,即未命名的slot</p>

    <templete v-slot:footer>
        <h1>将插入footer slot中</h1>
    </templete>
</NameSlot>

// NameSlot子组件
<div class="container">
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>

​

5.动态组件

  • :is="component-name"用法
  • 需要根据数据,动态渲染的场景。即组件类型不确定

例如:新闻详情页,组件类型不确定

​
// 父组件
<div v-for="(val, key) in newsDate" :key="key">
    <component :is="val.type"/>
</div>

<script>
import Text from './Text'
import Image from './Image'
import Video from './Video'
export default {
    data() {
        return {
            newsDate: {
                1: {
                    type: 'Text'
                },
                2: {
                    type: 'Image'
                },
                3: {
                    type: 'Video'
                },
            }
        }
    }
}
</script>

​// 子组件

6.异步组件

  • import()函数
  • 按需加载,异步加载大组件
// 父组件
// 同步引入:加载页面即引入,如果组件体积特别大,影响性能
// 异步引入:什么时候用,什么时候加载,优化性能
<script>
    // import FormDemofrom './FormDemo'
    export default {
    components: {
        // FormDemofrom ,
        FormDemo: () => import('./FormDemo'),
    },
</script>

7.keep-alive

  • 缓存组件(不会重复渲染和销毁,优化性能)
  • 频繁切换,不需要重复渲染
  • Vue常见性能优化
<template>
    <div>
        <button @click="changeState('A')">A</button>
        <button @click="changeState('B')">B</button>
        <button @click="changeState('C')">C</button>

        <keep-alive> <!-- tab 切换 -->
            <!--v-if根据条件渲染和销毁组件-->
            <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>

8.mixin

  • 多个组件有相同的逻辑,抽离出来
  • mixin 并不是完美的解决方案,会有一些问题
  • Vue3 提出的Composition API旨在解决这些问题

mixin问题:

  • 变量来源不明确
  • 多mixin可能会造成命名冲突
  • mixin和组件可能出现多对多的关系,复杂度较高
​
​
// 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)
    }
}

​

​

使用

​
​
<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: '张三',
            major: 'web 前端'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}
</script>

​

​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值