day-099-ninety-nine-20230626-Vue的学习路线-常用的vue指令-v-model-vue常见面试题
Vue的学习路线
- 如何学习Vue?
- 第一条线:视图线
-
<template>
或jsx语法
- 指令「内置的14个指令和自定义指令」
- jsx语法
- VirtualDOM编译的机制
- 掌握DOM-diff算法
- …
-
- 第二条线:数据线
- 学习
OptionsAPI
/CompositionAPI
中的:语法、原理、区别等内容- OptionsAPI选项
- 学习 MVVM 的原理
- 数据是如何被监听的「Vue2和Vue3是不一样的」
- 看第98天,数据劫持。
- 监听数据变化后,如何通知视图更新「观察者模式」
- 如何监听视图的变化,以及如何让状态跟着更改「v-model」
- 数据是如何被监听的「Vue2和Vue3是不一样的」
- 学习
- 第三条线:组件化开发
- 单文件组件「含
样式私有化方案
的原理」 -
类组件
和函数组件
- 复合组件通信
- 组件封装的技巧「各种封装技巧」
- 通用业务组件
-
UI组件库
的二次封装
- 通用功能组件
- Vue.mixin
- Vue.directive
- Vue.extend
- …
- 单文件组件「含
- 第四条线:实战线
-
vuex
/vue-router
- …
-
<keep-alive>
组件状态缓存 -
<transition>
组件动画 -
<component>
动态组件 -
上拉刷新
、下拉加载
-
超长列表
性能优化 -
登录
/权限管理模型
- 前后端数据通信管理方案
- …
-
- 第一条线:视图线
vue中的template语法
-
Vue中的
<template>
语法:-
小胡子语法:
- 小胡子语法
{{}}
:渲染数据。 -
小胡子语法{{}}
中渲染的是js表达式
,可以理解为有返回值的东西。- 数据值-最后都会被转换为字符串进行渲染。
- 原始值类型:
-
无法直接渲染Symbol()/BigInt()这两个函数。
<template> <div id="app"> Symbol('sym')-{{ Symbol('sym') }}<br /> </div> </template>
-
如果需要渲染唯一值/大数,需要在js中把相关的值赋值给状态/实例,再再小胡子中渲染。
<template> <div id="app"> sym-{{ sym }}<br /> </div> </template> <script> export default { name: "App", data() { return { sym: Symbol('sym'), }; }, }; </script>
- 扩展:只有限定的一些内置函数,才可以直接在小胡子中使用。比如:Number()/String()/Boolean/parseInt/JSON.stringify…
- 基本上都是专门做数据类型转换的。而如eval()这类方法就不行了。
- 扩展:只有限定的一些内置函数,才可以直接在小胡子中使用。比如:Number()/String()/Boolean/parseInt/JSON.stringify…
-
-
null/undefined 会渲染为空。
-
其余原始值类型,都会
基于String()转换为字符串渲染
。
-
- 对象类型
-
如果是普通对象和数组对象,其内部会基于JSON.stringify把其变为json字符串进行渲染。
-
而其余的对象类型值,都是
基于String()把其变为字符串进行渲染
。<template> <div id="app"> num-{{ num }}<br />渲染的值为0,而不是10。 </div> </template> <script> let num = new Number(10) num[Symbol.toPrimitive] = function(){ return '0' } export default { name: "App", data() { return { num, }; }, }; </script>
- 而不是通过toString()进行处理。
-
- 原始值类型:
- 变量/状态
- 数学运算(或者其它的计算)
- 如:取余数、位运算
- 判断:三元运算符-即三目运算符
条件?xxx:xxx
- 循环:利用数组的迭代方法进行处理(例如:map/filter)
- 数组的迭代方法: forEach/map/filter/find/findIndex/some/every/reduce/reduceRight
- Array.prototype.forEach()()
- Array.prototype.map()
- Array.prototype.filter()
- Array.prototype.find()
- Array.prototype.findIndex()
- Array.prototype.some()
- Array.prototype.every()
- Array.prototype.reduce()
- Array.prototype.reduceRight()
- 数组的迭代方法: forEach/map/filter/find/findIndex/some/every/reduce/reduceRight
- …
- 数据值-最后都会被转换为字符串进行渲染。
- 小胡子语法
-
根节点数量:
-
在Vue2中,每一个组件的视图,出现一个根节点。
<template> <div> 10<br /> </div> <button>55</button> </template>
- 会报错。
-
而Vue3中,是允许出现多个根节点的。
<template> <div> 10<br /> </div> <button>55</button> </template>
- 不会报错。
-
-
-
vue指令:
- Vue中提供的内置指令-14个和自定义指令。
- 对应的面试题:项目开发中,常用的Vue指令有那些?
- 以及各个指令中的一些细节和原理。
- Vue中提供的内置指令-14个和自定义指令。
-
vue的css样式:
- 如何设置样式。
- 对应的面试题:Class 与 Style 如何动态绑定?
- 样式私有化方案。
- 对应的面试题:在Vue组件
<style lang="less" scoped>
中编写的样式没有生效,都可能存在那些原因?以及该如何解决?
- 对应的面试题:在Vue组件
- 如何设置样式。
常用的vue指令
-
面试题:项目开发中,常用的Vue指令有那些?
- 回答:
- 我记得,之前看Vue的官方文档,貌似它提供的内置指令大约有14个左右吧,具体多少个有点记不清了。但是我在之前开发中,学用到的指令基本就是下面这些:
-
v-model,主要实现MVVM双向数据驱动中的:视图更新-即表单内容改变,可以让对应的状态也跟着更改。
- 我觉得,vue中的v-model非常好用,尤其是处理表单元素的时候,如果没有这个指令,还需要自己手动做事件监听,去手动修改状态值,这样就比较麻烦了!
- 而且我之前封装通用组件的时候,也会给组件设置v-model,以此来快速实现,子组件中的某些操作,可以实时修改父组件中的某些信息。
-
v-on,也就是
@
,主要是给元素做事件绑定的。-
这个指令的语法用起来很简单,尤其是不需要关注this/传参等问题,否则还需要自己基于bind来处理。
@click="fn" 点击执行 fn,传递事件对象 @click="fn(10,20)" 也是点击才执行 fn,传递一些实参值 @click="fn(10,20,$event)" 这样可以把事件对象传递进去
-
而且它还提供了很多事件修饰符,比如:stop/prevent/once/enter等等,而且还可以自定义按键修饰符,让开发起来开发效率和实现效果高很多!
-
我之前看过其内部处理机制,其实就是给元素基于addEventListener做事件绑定,所以我之前开发的时候,如果遇到循环事件绑定,我可能会基于事件委托去处理,而不会给每个循环元素单独绑定,也算是提高一些性能吧。
-
当然给子组件设置@符,不是绑定事件,而是使用了发布订阅机制!
-
-
v-show/v-if,都是控制元素的显示隐藏的。
- 只不过v-show只是控制元素的display样式值,不论值是什么,元素本身会被渲染。
- 都会触发重排与重绘。因为display也会触发重排。但该元素不会被销毁,vue内部不会重新创建对应的DOM元素。
- 而v-if其内部是控制元素的渲染和销毁,如果经常来回切换,性能会消耗比较大。
- 都会触发重排与重绘。因为display也会触发重排。对应的DOM元素会重新创建与销毁。
- 所以平时开发的时候,如果需要频繁进行显示隐藏的切换(比如:选项卡效果),使用v-show会更好一些!
- 但是如果切换不频繁(比如:第一次加载页面,没有数据先展示骨架屏,等待有数据后,再渲染真实的数据),我一般都是基于v-if来处理的!
- 不过有一点,
v-if="false"
的时候,元素是不会渲染的,此时如果想获取真实的DOM,必须基于v-show来处理,我之前项目中,实现触底加载,就遇到这样的问题!
- 只不过v-show只是控制元素的display样式值,不论值是什么,元素本身会被渲染。
-
v-for,主要用来循环绑定数据或者创建元素的。
- 不过要注意,v-for和v-if不要作用在相同的元素上,因为存在优先级问题。
- 而且要给v-for的元素设置唯一的key,只不过最好不要用索引作为key。
-
v-bind,也就是
:
,主要是用来给元素/组件的属性动态绑定值的。- 只要绑定的值不是字符串,或者是一个状态/属性等,都需要基于v-bind处理。
-
- 其余还有一些偶尔会使用的指令,比如:
- 基于v-html绑定内容,可以识别html标签。
- v-text一般不用,我都是直接用小胡子语法渲染了。
- v-if还对应了v-else-if/v-else。
- 以及处理插槽的v-slot。
- 最后还有几个优化类的指令:
- v-pre 可以让视图编译的时候,跳过某些元素,这些元素可以不编译。
- v-once 只让元素编译一次,以后组件更新就不再编译了!
- 这些一般都是用来处理那些静态内容,或者只需要渲染一次的内容的!
- 除此之外,我还会创建一些自定义指令,来实现一些需求,例如:我之前创建过v-power来处理项目的权限校验。创建过v-throttle来实现函数的节流等…
- 我记得,之前看Vue的官方文档,貌似它提供的内置指令大约有14个左右吧,具体多少个有点记不清了。但是我在之前开发中,学用到的指令基本就是下面这些:
- 回答:
-
回答完毕后的扩展问题?
-
1.
扩展:- 对应面试题:
v-model指令实现的原理?以及绑定给子组件后,其内部是如何处理的?
。
- 对应面试题:
-
2.
扩展:-
bind()
/call()
/apply()
- 面试官可能围绕
.stop修饰符
,问一些事件的传播机制
/事件委托
等,或者问一些常用的修饰符都有那些。 - 发布订阅设计模式?给子组件设置@符的目的?
- 修饰符:
.native
。 - …
-
-
4.
扩展:- v-for和v-if的优先级问题。
- 为什么不建议使用索引作为key?涉及DOM-diff算法。
- 其余扩展:
- 自定义指令的玩法和作用
- v-html的安全问题
- …
-
v-model
- 面试题:v-model指令实现的原理?以及绑定给子组件后,其内部是如何处理的?
- 先阐述一下v-model的作用,同上所述。
- v-model,主要实现MVVM双向数据驱动中的:视图更新-即表单内容改变,可以让对应的状态也跟着更改。
- 我觉得,vue中的v-model非常好用,尤其是处理表单元素的时候,如果没有这个指令,还需要自己手动做事件监听,去手动修改状态值,这样就比较麻烦了!
- v-model,主要实现MVVM双向数据驱动中的:视图更新-即表单内容改变,可以让对应的状态也跟着更改。
- 对于v-model的实现机制,我之前项目不忙的时候,自己去研究过,发现给不同元素/组件设置v-model,其内部的处理机制上是有所不同的!
-
给文本框/文本域设置v-model。
<input type="text" v-model="text1" />
<template> <div class="demo"> <!-- 文本框/文本域 --> <div> 基于v-model处理: <input type="text" v-model="text1" /> </div> <div>text1-{{ text1 }}</div> </div> </template> <script> export default { name: "FormDemo", data() { return { text1: "哈哈哈", }; }, }; </script>
-
其原理:
-
首先会把text状态值,赋值给表单元素的value属性。
-
而且自动给表单元素设置一个input事件(内容输入事件)的监听,当表单内容改变的时候,会获取表单中的最新信息,然后手动去修改text状态值。
<input type="text" :value="text2" @input="text2=$event.target.value" />
<template> <div class="demo"> <div> 如果没有v-model: <input type="text" :value="text2" @input="handle" /> </div> <div>text2-{{ text2 }}</div> </div> </template> <script> export default { name: "FormDemo", data() { return { text2: "呵呵呵", }; }, methods: { handle(ev) { console.log(`ev-->`, ev); this.text2 = ev.target.value; }, }, }; </script>
简写
<template> <div class="demo"> <div> 如果没有v-model-简写: <input type="text" :value="text3" @input="text3 = $event.target.value" /> </div> <div>text3-{{ text3 }}</div> </div> </template> <script> export default { name: "FormDemo", data() { return { text3: "嘿嘿嘿", }; }, }; </script>
-
-
而v-model还有对应的几个修饰符。
v-model.lazy.trim="text3"
-
.lazy:把监听的事件从input事件(内容输入),换为change事件(内容改变),这样可以降低事件触发的频率,类似于函数节流的效果!
<input type="text" :value="text2" @input="text2=$event.target.value" />
转成:
<input type="text" :value="text2" @change="text2=$event.target.value" />
-
.trim: 把表单中获取的内容,去除首尾空格后,再赋值给状态。
<input type="text" :value="text2" @input="text2=$event.target.value" />
转成:
<input type="text" :value="text2" @input="text2=$event.target.value.trim()" />
-
.number: 把表单中获取的内容,转换为数字类型后,再赋值给状态。
-
-
-
给单选按钮设置v-model。单选按钮一般都是同时出现两个及多个。
- 其步骤和原理:
- 给input[radio]绑定value属性,属性值就是当单选按钮被选中时,要赋值给状态的值。
- 再为其设置v-model指令,绑定一个状态信息。
- 在视图编译阶段v-model绑定值相同的,则他们会被分配到相同的组(容器存储),一组只能选中一个。
- 用绑定的状态值(sex),和各input[radio]中的value属性值进行比较,和谁一致,就让谁默认是选中态。
- 基于input事件,监听
各单选按钮input[radio]选择状态
的改变,从而去修改对应的状态值!
- 其步骤和原理:
-
给复选框设置v-model:
-
只有一个复选框:
<input type="checkbox" v-model="remember1">
- 基于v-model绑定的状态值(remember1),需要是布尔类型值。
- 状态值是true/false,决定了checkbox默认的选中状态。true选中,false不选中。
- 监听checkbox的change事件,当选中状态发生改变,对应的状态值(remember1)也会跟着更改。
-
有一组复选框:
<input type="checkbox" value="theA" v-model="remember2" />唱歌 <input type="checkbox" value="theB" v-model="remember2" />跳舞 <input type="checkbox" value="theC" v-model="remember2" />大刀 ...
- 给每一个checkbox设置value,存储的值就是后期选中时,想要获取的值。
- 首先基于v-model进行分组,绑定相同状态的为一组,一组可以选中多项,所以状态值需要是一个数组。
- 其次,根据现在的状态值,和各checkbox的value进行匹配,和谁匹配上,就让谁默认选中。
- 最后,监听每一个checkbox的change事件,当任意checkbox的选中状态发生改变,都会迭代所有的checkbox,把选中项的value获取到,赋值给对应的状态。
-
-
给下拉框设置v-model
<select v-model="city1"> <option value="">全部</option> <option value="北京">北京</option> ... </select>
- 其原理和给文本框/文本域绑定v-model类似。
-
首先把状态值赋值给select的value属性,控制其默认选中那一项。
-
最后监听select的change事件,在选择项改变的时候,把最新选中的value值赋值给状态!
<select :value="city2" @change="city2=$event.target.value"> <option value="">全部</option> <option value="北京">北京</option> ... </select>
-
- 其原理和给文本框/文本域绑定v-model类似。
-
给子组件设置v-model
<child-demo v-model="num1"></child-demo>
-
底层原理:
<child-demo :value="num1" @input="num1 = $event"></child-demo>
- 首先,把父组件的num状态值,基于value属性传递给子组件-子组件内部可基于props接收渲染。
- 其次,给子组件事件池中注入一个名为input的自定义事件,绑定的方法是num=$event。目的:修改父组件的num状态值。
- 最后,在子组件内部,可以基于$emit方法,通知input自定义事件执行,传递的第一个实参值就是为父组件的num状态改的值!
- 代码:
this.$emit("input", 20000);
- 代码:
- 基于这样的机制,可以实现:父组件把状态信息基于属性传递给子组件,子组件内部也可以直接修改父组件的这个状态值,实现父子组件之间的实时通信。
-
在子组件中,我们还可以基于model配置项,自定义来自于父组件中v-model传递的属性/自定义事件的名称!
model: { prop: 'value', event: 'update' }
相当于父组件这样调用:
<child-demo :value="num" @update="num = $event" />
- 说明:
-
在子组件中这样设置:
<script> export default { model: { prop: "modelPropValue", event: "update", }, }; </script>
-
在父组件中
<template> <child-demo v-model="num1"></child-demo> </template>
就相当于在父组件中是这样调用子组件:
<template> <child-demo :modelPropValue="num1" @update="num1 = $event"></child-demo> </template>
-
- 说明:
-
上面全部的玩法,其实有更简单的处理方式,就是使用v-bind中的sync修饰符!
<B :x.sync="num"/>
-
基于 x 属性,把父组件的 num 状态值,传递给子组件
-
向子组件的事件池中,注入一个 update:x 的自定义事件
<B :x="num" @update:x="num = $event"/>
- 相比较于 v-model ,这种方式更加的灵活,无需基于 model 自定义 属性名/自定义事件名 了!而且可以给多个属性,都这是 .sync!
-
-
各版本类v-model功能对比:
-
v-bind:属性名.sync
版:-
fang/f20230626/day0626/src/views/MyA.vue
<template> <div> 父组件<br /> num1-{{ num1 }} <br /> <br /> <MyB :x.sync="num1"></MyB> </div> </template> <script> import MyB from "./MyB.vue"; export default { components: { MyB, }, data() { return { num1: 100, }; }, }; </script>
-
fang/f20230626/day0626/src/views/MyB.vue
<template> <div> <button @click="handle">子组件的按钮 :属性名.sync</button> <div>父组件的传递进来的状态是:x-{{ x }}</div> </div> </template> <script> export default { props: ["x"], methods: { handle() { this.$emit("update:x", this.x + 1); }, }, }; </script>
-
-
v-model
版:-
fang/f20230626/day0626/src/views/MyA.vue
<template> <div> 父组件<br /> num1-{{ num1 }} <br /> <br /> <!-- <MyB :x="num" @update:x="num=$event"></MyB> --> <MyB v-model="num1"></MyB> </div> </template> <script> import MyB from "./MyB.vue"; export default { components: { MyB, }, data() { return { num1: 100, }; }, }; </script>
-
fang/f20230626/day0626/src/views/MyB.vue
<template> <div> <button @click="handle">子组件的按钮 v-model</button> <div>父组件的传递进来的状态是:x-{{ x }}</div> </div> </template> <script> export default { model: { prop: "x", event: "update:x", }, props: ["x"], methods: { handle() { this.$emit("update:x", this.x + 1); }, }, }; </script>
-
-
v-bind:属性
与v-on:自定义事件@
版:-
fang/f20230626/day0626/src/views/MyA.vue
<template> <div> 父组件<br /> num1-{{ num1 }} <br /> <br /> <MyB :x="num1" @update:x="num1=$event"></MyB> </div> </template> <script> import MyB from "./MyB.vue"; export default { components: { MyB, }, data() { return { num1: 100, }; }, }; </script>
-
fang/f20230626/day0626/src/views/MyB.vue
<template> <div> <button @click="handle">子组件的按钮 `v-bind:属性`与`v-on:自定义事件@`</button> <div>父组件的传递进来的状态是:x-{{ x }}</div> </div> </template> <script> export default { props: ["x"], methods: { handle() { this.$emit("update:x", this.x + 1); }, }, }; </script>
-
-
-
-
- 先阐述一下v-model的作用,同上所述。
复合组件
- 复合组件:就是组件之间的嵌套
- 父子
- 兄弟
- 祖先和后代
- 平行组件
- …
父子组件间的事件绑定
- 给子组件设置v-on(@),并非是给子组件做事件绑定,而是:给子组件的事件池中,注入一个自定义事件。
- 在vue2中,每一个类组件都有一个自己的事件池(容器)。
- 下面的操作相当于向子组件事件池中,加入了一个叫做input的自定义事件,值就是后面绑定的方法。
- 在子组件内部,可以基于$emit通知这个自定义事件执行,并且传递实参值。
vue中的组件
-
Vue中的组件:
-
采用单文件组件的方式
Xxx.vue
<template></template> <script> export default { .... } </script> <style lang="less" scoped></style>
-
-
创建一个单文件组件,其实默认就是私有/局部组件。
-
组件的使用:
-
局部组件
-
如果某个组件/页面中需要用到局部组件,则
- 导入
- 注册
- 调用
<template> <div id="app"> <FormDemo>3.大驼峰方式调用</FormDemo> <form-demo>3.连字符方式调用</form-demo> </div> </template> <script> import FormDemo from "./views/FormDemo.vue"; //1.导入; export default { name: "App", components: { FormDemo, //2.注册。 }, }; </script> <style lang="less"></style>
-
-
全局组件
- 导入指定的组件
- 注册:Vue.component(组件名,组件)
- 在其它的组件或者页面中,直接使用即可!
-
写在methods中的函数
- 写在 methods 中的函数
- 这些函数会直接挂载到实例上「可以基于this.xxx访问,而且视图中可以直接使用」
- 函数中的this都是当前组件/类的实例
vue常见面试题
- 谈谈你对 MVVM / MVC 模式的理解?
- 在day-098。
- Vue2框架怎么实现对象和数组的监听?「Vue2响应式原理」
- 在day-098。
- v-model指令实现的原理?
- v-show 与 v-if 有什么区别?
- Class 与 Style 如何动态绑定?
- computed 和 watch 的区别和运用的场景?
- 谈谈你对 Vue2 生命周期的理解?
- Vue怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
- 项目开发中,常用的Vue指令有哪些?
Vue2框架常见的面试题
- Vue2框架常见的面试题
- Vue怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
- v-show 与 v-if 有什么区别?
- Class 与 Style 如何动态绑定?
- 开发中常用的Vue指令有哪些
- 在 Vue 组件
<style lang='less' scoped>
中编写的样式没有生效,都可能存在哪些原因?以及该如何解决? - computed 和 watch 的区别和运用的场景?
- 谈谈你对 Vue2 生命周期的理解?
- 简单说一下 $nextTick 的作用及实现原理?
- Vue 组件中的 data 为什么必须是函数?
- 说一下 .native / .sync 修饰符的作用及原理!
- 怎样理解 Vue 的单向数据流?
- Vue 组件间通信有哪几种方式?
- 父组件可以监听到子组件的生命周期吗?
- 平时开发中,你有没有封装过公共组件?如果封装过,则简单说一下你当时是怎么考虑的!
- 介绍一下你对vuex的理解?
- vuex 页面刷新数据丟失怎么解决?
- 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
- 介绍一下路由的两种实现模式:hash模式 和 history模式
- 介绍一下 vue-router 中的导航守卫函数
- 说一下路由跳转的方案及传参方式有哪些?
- 介绍一下你对vue-router的理解?
- vue中组件和插件有什么区别?
- 说说你对Vue.mixin的理解,有什么应用场景?
把一个值转换为字符串
-
把一个值转换为字符串文章来源:https://www.toymoban.com/news/detail-503228.html
-
String(value)
-
String(value)
: 内部有一套机制。- 先调用 value[Symbol.toPrimitive] :看是否有这个方法;
- 如果没有上面的方法,再调用 valueOf() ,看获取的是否是原始值;
- 如果不是原始值,最后调用 value.toString() ;
-
-
value.toString()
-
value.toString()
: 直接调用其原型链上找到的方法;
-
-
-
String处理的时候,会执行一个完整的处理逻辑文章来源地址https://www.toymoban.com/news/detail-503228.html
- Symbol.toPrimitive
- 不过如果是实例原型上本身就有,有些eslint或一些框架如vue中不允许修改默认内置属性。
- valueOf
- toString
- Symbol.toPrimitive
进阶参考
到了这里,关于20230626----重返学习-Vue的学习路线-常用的vue指令-v-model-vue常见面试题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!