Vue知识点汇总

1 基本使用

1-1 模板(插值表达式,指令)

{{}}

v-html(有xss风险,会覆盖子元素)

1-2 computed和watch

  1. computed有缓存,data不变时不会重新计算
  2. watch深度监听
  3. watch监听引用类型无法拿到oldValue

1-3 class和style

class 使用动态属性

  1. 对象式
  2. 数组式
<p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
<p :class="[black, yellow]">使用 class (数组)</p>

style 使用驼峰式写法

styleData

<p :style="styleData">使用 style</p>
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }

1-4 条件渲染

v-if/v-else/v-else-if, v-show

  • 可使用变量或者===表达式
  • 必须是兄弟html元素

v-if 和 v-show 的区别

  • v-if 条件渲染,会触发创建和销毁
  • v-show 条件显示,创建后不再销毁,切换仅仅是注释掉

v-if 和 v-show的使用场景

  • v-if 适用于切换不频繁的场景
  • v-show 切换频繁时使用

1-5 循环

v-for

  • 数组:v-for="{{ item, index}}"
  • 对象:v-for"{{ val, key, index}}"

key使用

  • 尽量是一个数据的唯一值
  • v-for和v-if不能在一个元素上同时使用,可分别用在子父元素

1-6 事件

v-on/简写为@,可写事件名或者表达式

event参数,自定义参数

  1. 不传入参数时,默认事件第一个参数为事件对象
  2. 传入参数时,要获取事件对象则需要传入$event
  3. event是原生的
  4. 事件被挂载到当前元素

修饰符

事件修饰符
  1. .stop 阻止点击事件传播
  2. .prevent 提交事件不再重载页面
  3. .capture 添加监听事件时使用事件捕获模式,即内部元素触发的事件先在此处理,然后再交给内部元素
  4. self 只在event.target是自身时触发
按键修饰符
  1. @click.ctrl 同时按下alt或者shift也会触发
  2. .ctrl.exact 只有同时按下ctrl时才会触发
  3. @click.exact 没有同时按任何修饰符时才会触发

观察事件被绑定到哪里(与react有所不同)

1-7 表单

v-model

常见表单项

textarea
checkbox
radio
select

修饰符

lazy
number
trim

2 组件

2-1 props

父组件通过v-bind绑定动态属性传参

// index.vue
<template>
    <div>
        <Input @add="addHandler"/>
        <List :list="list" @delete="deleteHandler"/>
    </div>
</template>

子组件接收父组件参数

list.vue
    props: {
        // prop 类型和默认值
        list: {
            type: Array,
            default() {
                return []
            }
        }
    },

2-2 v-on 和 $emit

子组件触发事件删除父组件数据

<template>
    <div>
        <ul>
            <li v-for="item in list" :key="item.id">
                {{item.title}}
                <button @click="deleteItem(item.id)">删除</button>
            </li>
        </ul>
    </div>
</template>

由于单向数据流的原因,需要使用$emit提交事件给父组件,让父组件操作

// List.vue
// ...
    methods: {
        deleteItem(id) {
            this.$emit('delete', id)
        },
        addTitleHandler(title) {
            // eslint-disable-next-line
            console.log('on add title', title)
        }
    },

子组件emit 中的事件名对应 父组件中的事件名
在这里插入图片描述
父组件实现数据删除操作

	// index.vue
	// ...
    methods: {
        deleteHandler(id) {
            this.list = this.list.filter(item => item.id !== id)
        }
    },

2-3 组件通讯-自定义事件

创建用于自定义事件的Vue实例

创建一个Vue的实例专门用于创创建自定义事件,因为Vue里有一个自定义事件的方法
在这里插入图片描述

event.$on 绑定自定义事件

// list.vue
    mounted() {
        // eslint-disable-next-line
        console.log('list mounted')

        // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)
    },

event.$emit 调用自定义事件

// Inout.vue
    methods: {
        addTitle() {
            // 调用父组件的事件
			// ...
            // 调用自定义事件
            event.$emit('onAddTitle', this.title)
            this.title = ''
        }
    }

及时在beforeDestroy时销毁自定义事件

    beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }

2-4 组件生命周期

  1. 创建阶段
  2. 挂载阶段
  3. 更新阶段
  4. 销毁阶段
    在这里插入图片描述

mouted 和 created的区别

  • mouted是页面已经渲染完成
  • created 是页面未渲染完成,但是vue实例 已经初始化完成

单个组件

父子组件

在这里插入图片描述

创建与挂载顺序
  1. 父组件先创建js模型,初始化vue实例,然后子组件创建
  2. 子组件先挂载,渲染页面,父组件再挂载
    在这里插入图片描述
更新顺序

在这里插入图片描述

类似于洋葱模型

3 高级特性

3-1 自定义v-model - 使用model选项

<template>
    <!-- 例如:vue 颜色选择 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
</template>

<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>
  1. 上面的 input标签 使用了 :value 而不是 v-model
  2. 上面的 $emit提交事件change1 和 model.选项中的 event事件名 要对应起来
  3. text1 属性值要和model选项中的prop值对应起来

在这里插入图片描述

3-2 refs

ref属性,用于获取dom元素

只要元素上添加这个属性以及名称
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3-3 $nextTick vue组件更新之后获取最新DOM

  • 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()}`);

      // 获取 DOM 元素
      const ulElem = this.$refs.ul1;
      // eslint-disable-next-line
      console.log(ulElem);
      // eslint-disable-next-line
      console.log("普通获取", ulElem.childNodes.length);
      this.$nextTick(() => {
        // 获取 DOM 元素
        const ulElem = this.$refs.ul1;
        // eslint-disable-next-line
        console.log(ulElem);
        // eslint-disable-next-line
        console.log("使用$nextTick", ulElem.childNodes.length);
      });
    }
  }
};
</script>

使用$nextTick能立即拿到结果
在这里插入图片描述

总结

  1. 异步渲染,$nextTick 等待 DOM 渲染完再回调
  2. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次

3-4 slot 插槽

基本使用

父组件传数据给子组件,并调用子组件

        <SlotDemo :url="website.url">
            {{website.title}}
        </SlotDemo>
        ...
<script>
import SlotDemo from './SlotDemo'
export default {
    components: {
        SlotDemo,
    },
    data() {
        return {
            name: 'lc',
            website: {
                url: 'http://bilibili.com/',
                title: '哔哩哔哩弹幕网',
                subTitle: '看番网站'
            },
        }
    }
}
</script>

子组件接受数据,设置插槽

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

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

子组件<slot>标签下就会被父组件调用子组件时写入的内容替换
在这里插入图片描述
不给父组写内容就会展示子组件默认的内容
在这里插入图片描述

作用域插槽 v-slot

让父组件获取到子组件数据,并传入插槽
子组件设置数据

export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://baidu.com/',
                title: '百度',
                subTitle: '百度一下,你就知道'
            }
        }
    }
}

如果想要使父组件可以传入子组件的数据该怎么办?

首先给子组件插槽设置一个动态属性
在这里插入图片描述
父组件设置v-slot指令,等于一个自定义数据名
在这里插入图片描述
这样子组件数据就通过v-model传入了自定义数据名slotProps
通过以下方式获取数据,第二个slotData需要和子组件动态属性名对应

{{slotProps.slotData.title}}

具名插槽

插槽多了之后,可以给插槽命名,用于区分并对应插入
子组件定义插槽名

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

父组件通过slot:slotName对应插入

        <SlotDemo :url="website.url">
            <template  v-slot:s1>
                <div>
                    s1
                </div>
            </template>
            <template  v-slot:s2>
                <div>
                    s2
                </div>
            </template>
            <template  v-slot:s3>
            </template>
        </SlotDemo>

在这里插入图片描述

3-5 动态组件

  • 有的时候,我们需要在多个不同的组件之间进行切换。
  • 虽然我们可以通过 v-if来处理,但是会比较麻烦,而且有些问题
    • 有销毁过程,如果频繁切换,开销大
    • 无法保存组件状态
  • 使用v-show同样会有问题
    • 无论后续是否切换组件,组件都会统一进行渲染
    • 组件结构在html中可以查看
  • vue 提供了一个更方便的方式来处理这种情况

component 组件

  • componentvue 内置的一个组件,它提供一个 is 属性用来动态渲染不同的组件
  • 但是当组件切换的时候,都会触发组件的销毁和重建。
  • 首先,性能不好。其次,会丢失组件状态
  • 所以后面会有keep-alive组件来优化这些问题
        <!-- 动态组件 -->
        <component :is="dynamicComponent"/>
    data() {
        return {
            dynamicComponent: "NextTick",
        }
    }

3-6 异步组件

  • import() 函数
  • 按需加载,异步加载大组件
  • 什么时候用,什么时候加载
        <!-- 异步组件 -->
        <FormDemo v-if="showFormDemo"/>
        <button @click="showFormDemo = true">show form demo</button>

点击切换状态,然后通过v-if判断加载组件

    data() {
            showFormDemo: false
        }
    }

在这里插入图片描述
点击才会发送请求加载,这就是异步组件

3-7 keep-alive 组件持久化-缓存组件

keep-alive 组件

当在这些组件之间切换的时候,有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。keep-alive 是一个内置容器组件, 使用 >keep-alive 以后,内部包含的组件将增加 激活失活/冻结 的状态

使用格式<keep-alive><component :is=""></component></keep-alive>

        <keep-alive>
            <!-- is 接收的是要显示的组件名称 -->
            <component :is="currentComponent"></component>
        </keep-alive>

这样只会在第一次切换组件的时候调用生命周期中的mounted/created函数
并且不再调用destroyed函数销毁组件

keep-alive 生命周期

使用了 keep-alive 的组件会触发 activateddeactivated 两个生命周期函数

activated

keep-alive 组件激活时调用

deactivated

keep-alive 组件停用时调用

3-8 mixin 混合-抽离组件公共逻辑

  • 多个组件有相同的逻辑,可以抽离出来多个组件共用
  • mixin 并不是完美的解决方案 会有些问题
  • Vue3 提供了 Composition API 用于解决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)
    }
}

组件通过mixins: [myMixin]格式混入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: 'lc',
            major: 'web 前端'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}
</script>

组件就能直接拿到mixin中的数据,相当于复制进来了

缺点:

  • 变量来源不明确,不利于阅读
  • 多个mixin可能造成命名冲突,造成数据覆盖的情况
  • mixin可能出现多对多的引用关系,复杂度高, 耦合性很高

3 vuex

通信解决方案

通信核心:找到数据交互之间的桥梁。如果两者之间能直接沟通,那就直接沟通,如果不能,则找一个两者都能说得上话的人。

  • props/$emit(父子通信)
  • $refs/ref(父子通信)
  • children/parent(父子通信)
  • attrs/listeners(父子通信)
  • provide/inject(父子通信、跨级通信)
  • eventBus(父子通信、跨级通信、兄弟通信)
  • localStorage/sessionStorage等基于浏览器客户端的存储(父子通信、跨级通信、兄弟通信、路由视图级别通信)
  • vuex(父子通信、跨级通信、兄弟通信、路由视图级别通信)

vuex

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式,类似 redux
vuex(父子通信、跨级通信、兄弟通信、路由视图级别通信)

在这里插入图片描述

  • state : 存储应用状态数据(React 中的 State)
    • mapStatestorestate 通过 mapState 函数映射到组件的 computed
  • getters类似组件的 datacomputedstore 也提供了一个 getters 对象来处理派生数据
    • mapGetters
  • Vue Component : 消费 State
  • actions : 提交修改 State 的动作(React 中的 action)异步操作只能在此执行
    • mapActions
    • dispatch
  • mutations : 唯一更改 State的位置(React 中的 Reducer)
    • mapMutationsmapMutations 函数的使用与 mapStatemapGetters 类似,但是其一般是把组件的 methods 映射为 storemutationscommit 调用
    • commit

vue-router

路由模式

  • hash模式(默认):http://baidu.com/#/user/10
  • H5 history 模式:http://abc.com/user/10 (需要server端支持)

路由配置

笔记

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值