Vue3自考题
1,如何使用vue3的组合式api
答:
- 在普通的前端项目工程中,在script标签中增加setup即可使用api
- 使用setup()钩子函数
2,computed 与各个watch之间和method的区别
答:
注意:
- 不要在计算属性中进行异步请求或者更改DOM
- 不要直接修改computed的值
区别:
- 计算属性值基于其响应式依赖被缓存,意思就是只要他之前的依赖不发生变化,那么调用他只会返回之前缓存的结果,而watch是监听的对象发生变化,则会被触发,方法则是每次重新渲染或者手动调用就会发生变化
3,如何进行样式绑定
答:
-
使用 :class 进行绑定
<div :class="{ active: isActive }"></div> //绑定一个对象 编译后: <div class="hello"></div> <div :class="[activeClass, errorClass]"></div> //绑定一个数组 编译后: <div class="activeValue errorValue"></div> let isActive = "hello" let activeClass = "activeValue" let errorClass = "errorValue"
-
使用内联样式进行绑定
<div :style="{ 'font-size': fontSize + 'px' }"></div>
4,v-if 与 v-show 的应用场景和区别
答
应用场景:如果切换不是太频繁,则应该使用v-if,反之使用v-show
区别:v-if是销毁后在新建,v-show则是通过display:none来控制,v-show的性能比v-if的性能要高一些
5,v-if,v-for的优先级问题
答: vue2中v-for优先于v-if,vue3相反。不建议在同一节点同时使用vif,与v-for,如果想过滤一些数据的话,可以这样做
<div v-for="item in computedItems" :key="item.id" /> //computedItems是经过处理后的数据列表。
6,vue3 修改了数组的哪些方法,使其能监听响应式数组的变更方法
答:push(),pop(),shift(),unshift(),splice(),sort(),reverse()
7,vue3修饰符
- 事件修饰符
修饰符 | 说明 |
---|---|
.stop | 事件停止冒泡 |
.prevent(坡蕊温特) | 阻止标签默认行为 |
.capture | 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 |
.self | 只当在event.target 是当前元素自身时触发处理函数 |
.once | 事件将只会触发一次 |
.passive([ˈpæsɪv]) | 不阻止事件默认行为 |
- 按键修饰符
修饰符 | 说明 |
---|---|
.enter | 按回车 |
.tab | TAB键 |
.delete | 删除键 |
.esc | ESC |
.space ([speɪs]) | 空格 |
.up||.down||.left||.right | 上下左右方向键 |
- v-model修饰符
修饰符 | 说明 |
---|---|
.lazy | 在每次 change 事件后更新数据 |
.number | 用户输入自动转换为数字,如果parseFloat()无法解析,那么则返回原始值 |
.trim | 去除用户输入值两端的空格 |
8,vue的生命周期
- vue2:
生命周期(页面) | 说明 |
---|---|
beforeCreate | 组件实例被创建之前,此时data还未生成。 |
created | 实例创建后,此时vm已经生成,但是还未挂载到页面上,el还未生成 |
beforeMount | 实例挂载前,此时vm即将要挂载到dom上,el还不生成 |
mounted | 实例挂载后,此时页面已经渲染成功,可以访问到el |
beforeUpdate | 实例数据更新前, |
updataed | 数据更新后 |
beforedestory | 实例销毁前,此时实例还未销毁 |
destoryed | 实例销毁后 |
生命周期(组件) | 说明 |
---|---|
actived | 被 keep-alive 缓存的组件激活时调用。 |
deactivated | 被 keep-alive 缓存的组件失活时调用。 |
- vue3:
生命周期(组合式API) | 说明 |
---|---|
onMounted | 在组件挂载完成后执行。ssr渲染不会被调用 |
onUpdated | 在组件因为响应式状态变更而更新其 DOM 树之后调用。ssr渲染不会被调用 |
onUnmounted | 在组件实例被卸载之后调用。ssr渲染不会被调用 |
onBeforeMount | 在组件被挂载之前被调用 |
onBeforeUpdate | 在组件即将因为响应式状态变更而更新其 DOM 树之前调用。 |
onBeforeUnmount | 在组件实例被卸载之前调用。 |
onErrorCaptured | 在捕获了后代组件传递的错误时调用 |
生命周期(组件) | 说明 |
---|---|
onActivated | 若组件实例是 KeepAlive 缓存树的一部分,当组件被插入到 DOM 中时调用 |
onDeactivated | 注册一个回调函数,若组件实例是 KeepAlive 缓存树的一部分,当组件从 DOM 中被移除时调用。 |
生命周期(选项式API) | 说明 |
---|---|
beforeCreate | 在组件实例初始化完成之后立即调用。 |
created | 在组件实例处理完所有与状态相关的选项后调用。 |
beforeMount | 在组件被挂载之前调用。 |
mounted | 在组件被挂载之后调用。 |
beforeUpdate | 在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。 |
updated | 在组件因为一个响应式状态变更而更新其 DOM 树之后调用 |
beforeUnmount | 在一个组件实例被卸载之前调用。 |
unmounted | 在一个组件实例被卸载之后调用。 |
errorCaptured | 在捕获了后代组件传递的错误时调用。 |
9,组件注册的方式
-
全局注册:vue.component
//语法 vue.component(componentName:string,template:components)
-
局部注册
- setup注册:如果使用了setup函数,则在组件引入后,即可直接使用,而无需注册
- components:直接在里面注册,然后在template模板中直接引用
10,组件接收prop的方式
-
组合式api:使用defineProps函数
let props = defineProps({ prop1 })
-
选项式api:props
props:{ prop1, }
11,vue哪个生命周期才能访问dom,为什么
- vue在mounted实例挂载后才可以访问dom,因为此时vue实例已经挂载到了el上
12,组件中的data为什么是个函数
答:因为vue中组件是复用的,如果组件中的data返回的是个对象的话,那么在多个组件同用一个data的时候,往往这个组件中的data发生了改变,那么其他组件也会发生改变。为了避免这个问题,就必须返回一个函数,这就相当于为每个组件开辟了一个私有的data
13,什么是MVVM?
- MVVM是一种设计思想,M代表的是model,V代表的是视图,VM代表的是控制器,负责的是视图与数据模型的交互
- MVVM能实现前端开发和js逻辑层的分离
14,vue2组件的通信方式
答:
- 父传子:父组件直接在子组件上绑定属性,然后子组件用props来接收
- 子传父:子组件使用**$emit(‘eventName’,params)**来向父组件传递信息,父组件使用on来监听子组件传递过来的事件,在methods中进行处理
- 父传子孙:使用provide 分发 ,inject接收
- 使用eventBus.js
- 插件使用vuex
15,如何实现vue首屏加载优化的?
- 把不常改变的库放到index.html中,用cdn来引入
- 使用路由懒加载
- 一些较小的图片使用base64格式返回
- 使用轻量型的工具库
- vue组件尽量不要全局引入
- 使用雪碧图(将多个小图片合并成一张大图,通过定位来控制位置)
16,vue项目性能优化
- 压缩代码
- v-if和v-for区分使用场景
- 路由懒加载
- 单页面使用keep-alive缓存
- 使用防抖节流
- 避免书写行内样式,以免造成重绘
- 使用轻量型工具库
- dll分包
17,watch与watchEffect的区别
答:
-
区别:
- watch只追踪明确侦听的数据源,仅在数据源确实改变时触发回调
- watchEffect则会在副作用发生期间追踪依赖,会在同步过程中,自动追踪所有能访问到的响应式属性
-
watchEffect的触发时机
-
语法
watch(source, callback, options) watchEffect(callback, options)
-
post:能在侦听器回调中访问被 Vue 更新之后的 DOM,他的另一个别名函数叫做:watchPostEffect()
-
sync:有必要在响应式依赖发生改变时立即触发侦听器的时候 别名:watchSyncEffect()
-
-
watch的options
watch (source: WatchSource<T>, callback: WatchCallback<T>, options?: WatchOptions) watchOptions:{ immediate ( [ɪˈmiːdiət] ):boolean, // 侦听器创建时立即触发回调。第一次调用时旧值是 undefined deep:boolean,//如果源是对象,强制深度遍历,以便在深层级变更时触发回调 flush:post|sync,//触发时机 onTrack / onTrigger:调试侦听器的依赖。 }
18,常用api参考
18.1,全局api
api | 说明 | 补充 |
---|---|---|
createApp(rootComponent:component,rootOptions:Object) | 创建一个vue实例 | Object是要传递给跟组件的props |
createSSRApp() | 从服务端创建一个实例 | 跟createApp一样的,区别是ssr |
app.mount(rootContainer: Element||string) | 将应用实例挂载在一个容器元素中。 | 对于每个应用实例,mount() 仅能调用一次。 |
app.unmount() | 卸载一个已挂载的应用实例。 | 卸载一个应用会触发该应用组件树内所有组件的卸载生命周期钩子。 |
app.provide(key:InjectionKey|symbol|string , value:T) | 提供一个值,可以在应用中的所有后代组件中注入使用。 | |
app.component(name: string, component: Component): this app.component(name:string ): Component|undefined |
如果传入一个组件名和一个组件,则代表全局注册一个组件,只传入一个组件名,那么返回一个组件或者undefined | this:指的是注册的组件 |
app.directive(name:string): directive|undefined app.directive(name: string, directive: directive): this |
注册指令 | this指的是指令 |
app.use(plugin: Plugin, …options: any[]): this | 安装一个插件。 | Plugin:插件 options:要传递给插件的选项。 this:返回的是插件本身 |
app.mixin(mixin: ComponentOptions): this | 混入 | vue3不推荐用了,可以用组合式函数来代替 |
18.2,通用api
api | 说明 | 补充 |
---|---|---|
nextTick(callback?: () => void): Promise | 等待下一次 DOM 更新刷新的工具方法。 | 常用来解决同步失效的问题 |
defineComponent(component: ComponentOptions | ComponentOptions[‘setup’]):ComponentConstructor | 在定义 Vue 组件时提供类型推导的辅助函数。 | 最大的用处就是给ts提供更好的类型推导 |
18.3,组合式api
api | 说明 | 补充 |
---|---|---|
setup(props,this) | 组合式api的入口 | props:组件的 props this:Setup 上下文对象 |
ref(value) | 把value变成一个ref代理对象,并把他返回来 | 默认访问属性需要value.value才能访问到 |
computed(getter:() => T) | 计算属性 | |
reactive(Object) | 返回一个对象的响应式代理。 | |
readonly(object) | 返回一个object的只读代理 | |
watchEffect(effect: (onCleanup: OnCleanup) => void, options?: WatchEffectOptions): StopHandle | 立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。 | StopHandle:返回一个停止监听 |
watchPostEffect() |
watchEffect() 使用 flush: 'post' 选项时的别名。 |
设置 flush: 'post' 将会使侦听器延迟到组件渲染之后再执行 |
watchSyncEffect() |
watchEffect() 使用 flush: 'sync' 选项时的别名。 |
在某些特殊情况下 (例如要使缓存失效),可能有必要在响应式依赖发生改变时立即触发侦听器。 |
watch (source: WatchSource, callback: WatchCallback, options?: WatchOptions) | 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。 | WatchOptions: |
响应式工具 | ||
isRef(r: Ref|unknown) | 检查某个值是否为 ref。 | 请注意,返回值是一个类型判定 (type predicate),这意味着 isRef 可以被用作类型守卫 |
unref(ref: T | Ref): T | 如果参数是 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 计算的一个语法糖 |
|
toRef(T extends object, K extends keyof T) | 基于响应式对象上的一个属性,创建一个对应的 ref。 | |
toRefs(T) | 将一个响应式对象转换为一个普通对象, | |
isProxy(value: unknown): boolean | 检查一个对象是不是proxy对象 | |
isReactive(value: unknown): boolean | 检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。 |
|
isReadonly(value: unknown): boolean | 检查传入的值是否为只读对象。 | |
依赖注入 | ||
provide(key: InjectionKey | string, value: T): void | 提供一个值,可以被后代组件注入。 | key:要注入的 key value:要注入的值 |
inject() | 注入一个由祖先组件或整个应用 (通过 app.provide() ) 提供的值。也可以理解为接收 |
19,keep-alive组件首次渲染,二次渲染触发的生命周期
答:
- 第一次进入触发的生命周期是:created -> mounted -> activated,退出时触发deactivated
- 第二次渲染时:只触发activated
20,如何实现动态添加keep-alive组件
通过路由中的meta对象下的keepAlive(boolean)属性来控制缓存组件是否缓存
语句:this.$route.meta.keepAlive=true||false
21,vue的优势
- vue是一种基于MVVM软件设计架构的轻量型框架
- vue可以进行组件化开发
- vue可以实现双向数据绑定
- vue视图和数据结构分离,
- vue的生态好,有丰富的ui框架以及插件
- vue不直接操作dom,vue是先通过diff算法生成ast树,然后通过pach算法比较差异,再生成dom树
- vue是单项数据流
22,虚拟dom的优缺点
- 保证性能下限
- 无需手动操作dom
- 跨平台
- 缺点是无法进行极致优化
24,解决跨域的方法
- 在vue.config.js中的devserve.proxy:{url:“地址”}中可以解决跨域
- 跨域是指不在同源策略(域名,协议,端口一致)内,就会产生跨域
- 也可以设置nginx(恩急壳死)反向代理来解决跨域
- 也可以用jsonp来解决跨域,只支持get调用
26,插槽slot简介
-
分类:
-
具名插槽:带有名字的插槽
//组件内 <component> <heander> <slot name = "header"></slot> //这个name就是插槽的名字 </header> </component> //使用组件 <componentName> <template v-slot:header> //v-slot后面跟的就是刚才设定的插槽名字 插槽内容 </template> </componentName>
-
匿名插槽:没有名字的插槽,一个标签只能有一个匿名插槽
-
作用域插槽:
<MyComponent v-slot="{ text, count }"> {{ text }} {{ count }} </MyComponent>
-
动态插槽名:
<base-layout> <template v-slot:[dynamicSlotName]> ... </template> <!-- 缩写为 --> <template #[dynamicSlotName]> ... </template> </base-layout>
-
-
缩写形式:#
-
作用:可以扩展组件,增加组件的灵活性
27,动态组件&异步组件
-
动态组件
动态组件需要用keep-alive标签
-
异步组件
异步组件需要使用vue.component(“组件名”,callback():promise),返回一个模板对象
28,vue双向绑定原理
-
vue2:
使用了Object.defineProperty结合发布者/订阅设计模式,递归遍历对象的每个属性,为每个属性都设置了setter/getter,一旦属性发生了变化,则通知相关的订阅者,订阅者调用setter直接改变对象的属性
-
vue3:
使用Proxy代理对象来实现。
29,render()函数的使用
- 使用场景:当场景中用template实现起来代码繁琐且有大量重复的时候
- render(contentHTML,htmlStyle,vNode),参数一:模板结构,参数二,模板样式,参数三,设置分发内容
30,父子组件的渲染过程,更新过程,销毁过程
- 渲染过程:父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子beforeMount -> 子mounted ->父mounted
- 更新过程:
- 父beforeUpdate -> 子beforeUpdate -> 子updated ->父updated —
- 子组件更新过程
- beforeUpdate -> updated
- 销毁过程:父beforeDestory -> 子beforeDestory -> 子destoryed ->父 destoryed
31,实现页面刷新几种方法,以及优缺点
- 使用this.$route.go(0)
- 优点:简单,方便,快,写的代码还少
- 缺点:会有一秒钟的白屏和闪烁。用户体验机器不好
- 使用location.reload():页面闪烁
- provide、inject和$nextTick:常用
- 新建空白页,利用
$router.replace
路由跳转到一个空白页面,然后在空白页面中立即执行$router.replace
切换到原来的页面
vuex 部分
1,vuex中状态存储在那里?如何去改变他?
答:存储在state中,改变state的状态只能通过mutation,或者通过Action使用commit触发mutation来改变状态111
2,vuex页面刷新数据丢失怎么办?
答:
- 把数据存到本地
- 使用vuex-persist (破尔色死特)插件
3,简述vuex得数据传递流程
- 使用dispatch||commit来触发action和mutition中得方法来改变state状态
- 使用getter来向外暴露state
- 然后在页面可以使用助手函数mapstate来获取vuex中得state,或者使用this.$store.state来获得数据
4,vuex中Mutation与Action得区别是什么?
- Mutation可以直接改变state得状态,这里进行得是同步操作
- Action不可以直接改变state得状态,不过这里可以进行异步操作
5,vuex嵌套的子模块中可以重复嵌套吗?
答:
可以,因为每一个子模块中都有 state,namespaced,mutations,actions,getters,modules,而且模块中多了一个属性namespace(命名空间),当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名,
6,vuex和pinia(皮尼啊)的区别
- Pinia 对 vue2 和 vue3 都支持,尤其是 TypeScript 的项目
- 没有模块的嵌套结构
- 不需要注入、导入函数、调用它们
- 无需手动添加 store ,它的模块默认情况下创建就自动注册的
- 支持 Vue DevTools
- 支持服务端渲染
- Vuex: State、Gettes 、 Mutations (同步)、 Actions (异步),modules(子模块)
Pinia: State、Gettes 、 Actions (同步异步都支持)
7,组合式api中如何使用vuex
答:
在组合式api中,需要先引入useStore函数import {userStore} form vuex
8,dispatch和commit的区别
- 相同点:二者最终都是用来提交mutation来更改state的值的
- 不同点:dispatch是异步提交,commit是同步提交
vue-router部分
1,怎么在组件中监听路由参数的变化
- 在watch直接监听$route(to,from)
- 在路由导航守卫中监听,beforeRouterEnter
2,Vue-router是干什么得?他得原理是什么
答:
vue-router是vue官方指定的路由插件,是单页面应用的核心组成部分,vue-router用于设定访问路径,并将路径和组件映射起来。传统多页面应用中,页面跳转是用超链接来实现页面切换和跳转的,但在单页面应用中,页面跳转则是使用路径的切换,路由的作用是建立url和页面的映射关系
vue-router的实现主要靠url中的hash和history中新增的接口来实现的。
3,路由间是如何跳转得?
- 在route-link中使用to属性来进行跳转
- 在js中使用this. r o u t e r . p u s h ( ) 或者 t h i s . router.push()或者this. router.push()或者this.router.replace(),或this. r o u t e r . g o ( ) , t h i s . router.go(),this. router.go(),this.router.back()来进行跳转
4,vue-router怎么配置路由
新建一个router文件夹,建立一个index文件,然后引入router,创建一个routers路由表,实例化一个router对象,使用这个路由表,设定mode
5,vue-router有哪几种路由守卫
-
全局守卫:
- beforeEach(to,from,next)
- afterEach
-
独享守卫:beforeEnter()
-
组件内守卫
- beforeRouterEnter
- beforeRouterUpdate
- beforeRouterLeave
6,路由传值的方式有几种?
-
编程式路由
- this.$router.push({name:“index”,params:{id:123}})
- 接收参数,在路由页面使用this.$route.params来接收
-
声明式路由
-
获取路由参数
this. r o u t e . p a r a m s , t h i s . route.params,this. route.params,this.route.query
7,route和router的区别
route是页面路由对象,他里面会有query,params等属性,router是全局路由对象mate路由元数据等
8,vue-router中常用的路由模式实现原理
- hash模式:利用window.hashChange来实现
- history:通过H5的history 新增的pushState和replaceState来实现
常用的库
库 | 说明 | 补充 |
---|---|---|
Lodash.js | Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。非常适用于:遍历 array、object 和 string 对值进行操作和检测 创建符合功能的函数 | |
PDF.js | 由js编写的pdf阅读器 | 用来解决小程序安卓端的pdf阅读问题 |
voca.js | 提供完整的函数集来操作、截断、格式化、转义和查询字符串 | |
video.js | 适用于vue的js视频播放器 | |
bowser.js | 适用于浏览器和节点的小型、快速且丰富的 API 浏览器/平台/引擎检测器。 | |
moment.js | 解析、验证、操作和显示日期。 | |
countdown.js | 倒计时插件 | |
dayjs | Day.js 是一款拥有和 Moment.js 一样的现代化接口的日期库,但它仅仅有 2kb 大小,可以用来替换 Moment.js。 | |
accounting.js | 对数字、金钱、货币进行格式化的轻量库,完全本地化和无依赖。 | 英文发音:鹅康听 |
chance.js | JavaScript 随机生成器,可以生成数字、字符串等。 | |
Vue I18n | 国际化vue插件 | 用来做中英适配 |
log | 浏览器日志插件 | 看日志更方便点 |
qs.js | qs.js是用来处理url中参数的一个js库 | |
js-cookie | 用于处理 cookie 的简单、轻量级 JavaScript API | |
flv.js | 一个用纯 JavaScript 编写的 HTML5 Flash 视频 (FLV) 播放器,没有 Flash。 | 哔哩哔哩开源的 |
mpegts.js | flv.js的迭代品 | |
Animate.css | 一个跨浏览器的 css3 动画库,内置了很多典型的 css3 动画,兼容性好,使用方便。 | |
animejs | 一款功能强大的 Javascript 动画库。可以与CSS3属性、SVG、DOM元素、JS对象一起工作,制作出各种高性能、平滑过渡的动画效果。 | |
mescroll.js | 一款精致的、在H5端运行的下拉刷新和上拉加载插件,主要用于列表分页、刷新等场景。 |
axios
1,axios是什么,怎么使用他,怎么解决跨域问题
- axios是基于promise的http库,是vue官方指定的http库
- axios需要npm install axios 和npm install vue-axios
- axios解决跨域需要在请求头加上content-type即可
移动端适配
1,解决方案
- postcss-px-to-viewport
- 使用rem+媒体查询
- 使用flex布局
小程序相关
1,哪些函数拥有页面跳转的功能?
- uni. navigateTo (Object):保留当前页面到路由栈中,然后跳转目标页面
- uni.redirectTo(Object): 关闭当前页面,跳转到应用内的某个页面。
- uni.reLaunch(Object):关闭所有页面,打开到应用内的某个页面。
- uni.switchTab():跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
- uni.navigateBack(Object):关闭当前页面,返回上一页面或多级页面
2,uniapp如何进行条件编译?
**写法:**以 #ifdef 或 #ifndef 加 **%PLATFORM%** 开头,以 #endif 结尾。
- #ifdef:if defined 仅在某平台存在
- #ifndef:if not defined 除了某平台均存在
- %PLATFORM%:平台名称
3,如何进行页面滚动监听
使用onPageScroll 生命周期函数监听
4,小程序切换tabbar,不触发onload怎么解决
在onTabItemTap()生命周期中写入代码
5,页面获取数据,渲染闪烁
可能页面上存在图片,但是没有指定高度。
6,小程序优化方案
-
核心点:
-
提高加载性能
-
加载流程:
-
代码包准备(下载代码包)优化措施:
- 分包加载
- 代码重构和优化:减少不常用的库引入和依赖
- 避免在代码包中包含过多,过大的图片,应尽量采用网络图片
- 清理无用代码
-
开发者代码注入
-
减少启动过程的同步调用
- 在小程序启动流程中,会注入开发者代码并顺序同步执行App.onLaunch(昂蓝吃),App.onShow,Page.onLoad,Page.onShow。
- 在小程序初始化代码(Page,App定义之外的内容)和启动相关的几个生命周期中,应避免执行复杂的计算逻辑或过度使用以Sync结尾的同步API,如:wx.getStorageSync,wx.getSystemInfoSync等。
- 对于getSystemInfo,getSystemInfoSync的结果应进行缓存,避免重复调用。
-
使用懒注入
通常情况下,小程序启动时,启动页面所在分包和主包(独立分包除外)的所有js代码会全部合并注入,包括其他未访问到的页面和未用到的自定义组件。影响注入耗时和内存占用-
开启仅注入当前页面需要的自定义组件和当前页面代码,在app.json中配置
{ "lazyCodeLoading":"requiredComponents" }
-
-
-
初次渲染
- 骨架屏:提升用户等待意愿
- 提升首屏数据请求
- 数据预拉取
- 周期性更新
- 精简首屏数据:
- 数据懒加载
- 数据合并
- 减少请求次数
- 数据局部更新
- 缓存请求数据:可以使用wx.setStorage,wx.getStorage等读写本地缓存的能力,来提升首屏数据渲染
-
-
-
提高渲染性能
- 及时清理定时器,因为小程序共享一个js运行环境
- 谨慎使用onPageScorll
- 合理封装组件:可以将一些高频执行setData的功能模块封装成组件,
- 图片懒加载:渲染页面时,只渲染出现在视图范围内的元素。
- 善用onload和onReady:
- onload是页面加载阶段,在onload阶段请求页面展示数据,
- onready是页面加载完成阶段,对于页面之后需要展示或者使用,但刚开始并不展示的数据可以在onReady阶段进行请求。
-
7,小程序登录流程
- 通过wx.login()获取code
- 向服务端发送code
- 服务端使用appid+appsecret+code登录凭证来对接微信接口服务
- 后端返回seesion_key+openId,
- 后端自定义登录态,与openid,session_key关联
- 后端返回给前端自定义登录状态
- 前端将登录状态存入本地(setStorageSync)
- 前端携带登录态发起业务请求
- 后端校验登录态,
- 后端返回业务数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2rO9rkJy-1676604621014)(https://res.wx.qq.com/wxdoc/dist/assets/img/api-login.2fcc9f35.jpg)]
原生js
1,检测数据类型
- 基本类型:typeof
- 复杂类型:instanceof, Array.isArray() , object.prototype.toString.call( type )
2,call , apply 的区别以及功能
功能:对象A调用对象b的方法。改变this的指向,call的性能会更好一些。
不同的地方:传递参数不同,apply接收数组,call 接收参数1,2,3
3,== 和 === 的区别
==会进行类型隐式转换,===不会
4,什么是同源策略
同协议,同域名,同端口
5,js中的数据类型
基本类型:number,string ,boolean,null,undefined,symbol,
引用类型:array,object,
6,pormise的优缺点
-
优点
- 统一异步api:
- 可以链式调用。
- 解决回调地狱(回调函数里嵌套回调函数)的问题
-
缺点
- 无法取消promise
- 如果不设置回调函数,promise内部抛出的错误,不会反应到外部
- 当处于pending状态时无法获取状态进展到哪个阶段。
- Promise 真正执行回调的时候,定义 Promise 那部分实际上已经走完了,所以 Promise的报错堆栈上下文不太友好。
7,浏览器的渲染过程
- 用户输入域名,然后dns解析成ip地址
- 浏览器根据ip地址请求服务器
- 服务器响应http请求,并返回数据给浏览器
- 浏览器开始渲染
- 根据html,生成dom树
- 根据css,生成css树
- 将html树与css树结合,生成render树
- 根据render树渲染页面
- 遇到script,则暂停渲染,优先执行js,然后继续渲染。
- 渲染完成。
8,哪些行为会造成内存泄漏
- 意外的全局变量
- 没有及时清除的定时器
- 脱离dom的元素引用(一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。)
- 持续绑定的事件(函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。)
- 闭包
- console.log不能被垃圾回收
9,async/await的优缺点,他和pormise的使用场景分别是
- **缺点:**await可能会造成线程阻塞
-
优点:
- 阅读性比较好。
- 可以直接写在条件判断里
- 使用场景:
- 并行的请求最好用pormise
- 不需要并行的时候,如果要传递参数,最好用pormise
10,Object 于与Map的区别:
-
共同点:都是键值对的动态集合,支持删除和增加键值对
-
不同点:
区别 Map Object 构造方式 let Map = new Map([
[“key”,“value”]
])let obj = {
key:value
}key的类型 any string||symbol key的顺序 有序(按照插入先后) 无序 size长度 通过访问Map.size属性 Object.keys() || for…in 访问方式 判断用has(),获取用get(),删除用delete(),获取所有keys(),清空clear() .
或者[]
迭代 keys(),value(),entries() for…in JSON序列化 JSON.stringify(Array.from(map)) 通过JSON.stringify()
11,宏任务和微任务
- 宏任务:
- 由宿主(浏览器或node)发起
- 包括:setTimeout,setInterval,MessageChannel I/O(消息通道),setImmediate(node环境),script(整体代码块)
- 微任务:
- 由js自身发起
- MutationObserver(浏览器环境),pormise.[then/catch/finally],process.nextTick(node环境)
- 执行顺序:
- 首先必须先执行所有的初始化同步任务
- 然后会检查微任务队列,并将其清空
- 接着取出第一个宏任务
- 当该宏任务执行完成,会检查这个宏任务中还有没有微任务,如果没有就执行下一个宏任务,如果有,则清空微任务。然后再执行下一个宏任务。
12,简述原型与原型链,原型链的作用有那些
- 原型:js声明构造函数时,会在内存中创建一个对应的对象,这个对象就是原函数的原型,构造函数中有个属性prototype就指向原型对象,而实例化出来的对象会拥有一个proto属性,也指向原型
- 原型链:当实例化的对象查找一个属性的时候,首先会在本身查找这个属性,如果没有,则去他的proto原型上去找,如果proto上没有,那么就去proto的原型中去找,这种链状过程就是原型链
- 作用:数据共享,节约空间,实现集成
13,什么是闭包?用途有那些?
-
如果一个函数访问了此函数的父级及父级以上的作用域变量,那么这个函数就是一个闭包。
-
用途:防抖(在指定时间内,用户多次触发事件只触发一次),节流(在指定间隔时间内,请求只发送一次)
-
例子
for(var i = 1;i<10;i++){ setTimeout(()=>{ console.log(i) },1000) } //11,11,11,11.... for(var i = 1;i<10;i++){ (setTimeout((j)=>{ console.log(i) }),1000)(i) } //1,2,3,4,5,6,7...
-
闭包的优点:
- 减少全局变量的定义数量,避免全局变量污染
- 读取函数内部变量
- 在内存中维护一个变量,可以用作缓存
-
闭包的缺点
- 造成内存泄露,消耗内存,影响网页性能,解决方法是用完他之后,把他设置成null
- 闭包可能在父函数外部改变父函数内部的值
TypeScript部分
1,将对象转化成数组
//type:类型别名 Record:用来定义对象的key和value 这句话的意思是定义一个key和value都是string类型的对象。
type Obj = Record<string,string>
//定义一个接口
interface FormatItem{
key:string,
op:string,
value:string,
}
function objToArray(obj:Record<string,Obj>) :FormatItem[]{
return Object.keys(obj).reduce((value:Array<FormatItem> , key:string)=>{
var op:string = Object.keys(obj[key])[0];
value.push({key:key,op:op,value:obj[key][op]});
return value;
},[])
}
console.log(
objToArray({
key1: {
op1: "value1",
},
key2: {
op2: "value2",
},
})
);
// result示例
// [
// {key: 'key1', op: 'op1', value: 'value1'},
// {key: 'key2', op: 'op2', value: 'value2'}
// ]
2,反转句子
/**
* @file 反转句子
*
* 同时满足以下条件:1、去除首尾空格,2、单词间隔中多个空格变成一个;
* 注意console示例运行结果
*/
function reverseWord(str: string) {
// 补全此处代码
return (<string[]>str.match(/\S+/g)).reverse().join(" ");
}
console.log(reverseWord('the sky is blue')); // blue is sky the
// 去除首尾空格
console.log(reverseWord(" hello world ")); // world hello
// 单词间隔中多个空格变成一个
console.log(reverseWord("a good example")); // example good a
export default {}
3,找出字符串中第一个只出现一次的字符
/**
* @file 找出字符串中第一个只出现一次的字符
*/
function firstSingleChar(str: string) {
// 参考答案
return str.split("").filter((item: string, index: number, arr: string[]) => {
arr.splice(index, 1);
return !arr.includes(item);
})[0];
}
// a 和 b 都出现了两次,只有 c 出现了一次,返回 c
console.log(firstSingleChar("abcba")); // c
// b c d 都出现了一次,返回第一个
console.log(firstSingleChar("aabcdee")); // b
// a 和 b 都出现了多次,没有只出现一次的元素,返回 undefined
console.log(firstSingleChar("aaaabbbb")); // undefined
console.log(firstSingleChar("dabvb"));
export default {};
4,合并两个有序数组
/**
* @file 合并两个有序数组
*/
function merge(arr: number[], arr2: number[]): number[] {
// 参考答案
return arr.concat(arr2).sort((a: number, b: number) => a - b);
}
// 参数数组从小到大排列
console.log(merge([1, 2, 3], [2, 5, 6])); // [ 1, 2, 2, 3, 5, 6 ]
export default {};
5,实现数组 map 方法
/**
* @file 实现数组 map 方法
*/
function myMap<T, R>(arr: T[], callbackFn: (v: T) => R): R[] {
// 参考答案
var arr1: R[] = [];
for (var i = 0; i < arr.length; i++) {
if (i in arr) arr1[i] = callbackFn(arr[i]);
}
return arr1;
}
// 测试
console.log(myMap([1, 2, 3], (v) => v * 2)); // [2, 4, 6]
export default {};
6, 二叉树所有路径
/**
* @file 二叉树所有路径
*/
type Tree = {
value: number;
left?: Tree;
right?: Tree;
};
const tree: Tree = {
value: 1,
left: {
value: 2,
right: { value: 5 },
},
right: { value: 3 },
};
function treePath(root: Tree): string[] {
// 补全此处代码
// throw new Error('功能待实现');
const answer: [] = [];
let tmp: [][] = [];
const travel = (r: Tree) => {
if (r == null) {
return;
}
//@ts-ignore
tmp.push(r.value);
if (r.left == null && r.right == null) {
//@ts-ignore
answer.push(tmp);
tmp = [tmp[0]];
return;
}
if (r.left) travel(r.left);
if (r.right) travel(r.right);
};
travel(root);
//@ts-ignore
return answer.map((t) => t.join("->"));
}
console.log(treePath(tree)); // [ '1->2->5', '1->3' ]
export default {};
7,树结构映射
/**
* @file 树结构映射
* 数组 map 保持数组长度相同,将对应位置元素进行映射。
* 与之类似,在二叉树 Tree 上的映射我们称为 mapTree,该函数返回一个结构相同的新树,对应位置 value 字段经过 fn 映射。
*/
type Tree = {
value: number;
left?: Tree;
right?: Tree;
};
function mapTree(tree: Tree, fn: (v: number) => number): Tree {
// 参考答案
if (tree == null) {
return tree;
}
tree.value = fn(tree.value);
if (tree.left) mapTree(tree.left, fn);
if (tree.right) mapTree(tree.right, fn);
return tree;
}
// 测试
const tree: Tree = {
value: 1,
left: { value: 2 },
right: { value: 3 },
};
console.log(mapTree(tree, (v) => v * 2)); // { value: 2, left: { value: 4 }, right: { value: 6 } }
export default {};
8,计算数组笛卡尔积
/**
* @file 计算数组笛卡尔积
*/
// 示例
console.log(product([1, 2], [3, 4])); // [[1, 3], [1, 4], [2, 3], [2, 4]]
function product(xList: number[], yList: number[]): [number, number][] {
// 参考答案
return xList.reduce((v, t) => {
return v.concat(yList.map((item) => [t, item]));
}, [] as [number, number][]);
}
export default {};
9,返回一个 Promise,并在 ms 毫秒后 Promise 变为完成状态
/**
* @file 返回一个 Promise,并在 ms 毫秒后 Promise 变为完成状态
*/
export function sleep(ms: number): Promise<undefined> {
// 参考答案
return new Promise(
(
resolve: (value: undefined) => void,
reject: (value: undefined) => void
) => {
setTimeout(() => {
resolve(undefined);
}, ms);
}
);
}
async function main() {
console.log("a");
await sleep(1000);
console.log("b");
await sleep(1000);
console.log("c");
}
main();
export default {};
10,实现 PromiseAll 方法
/**
* @file 实现 PromiseAll 方法
*/
import { sleep } from "./8.sleep";
async function myAll<T extends unknown[] | []>(
values: T
): Promise<{ [P in keyof T]: Awaited<T[P]> }> {
// 补全此处代码,使用 Promise.all 以外的语法完成
// throw new Error('功能待实现');
var arr = [];
for (var i = 0; i < values.length; i++) {
arr.push(await values[i]);
}
return arr as { [P in keyof T]: Awaited<T[P]> };
}
// 一秒钟后返回结果 value
async function request(value: string) {
await sleep(1000);
return value;
}
async function main() {
console.log("start");
const res = await myAll([request("a"), request("b"), request("c")]);
console.log(res); // 预期输出 start 一秒后输出 ['a', 'b', 'c']
}
main();
export default {};
11,假设加法是一个异步过程,如何计算多个数组之和?
/**
* @file 假设加法是一个异步过程,如何计算多个数组之和?
*/
function sleep(ms: number) {
return new Promise((r) => {
setTimeout(() => {
r(undefined);
}, ms);
});
}
async function asyncAdd(a: number, b: number) {
await sleep(1000);
return a + b;
}
async function sum(arr: number[]): Promise<number> {
// 参考答案
var s: number = arr[0];
for (var i = 1; i < arr.length; i++) {
s = await asyncAdd(s, arr[i]);
}
return s;
}
console.time("a");
sum([1, 2, 3, 4, 5, 6, 7, 8]).then((v) => {
console.log(v); // 36
console.timeEnd("a"); // a: <耗时>
});
export default {};
12,typescript的主要特点是什么?
- 跨平台:ts编译器可以安装在任何平台上
- es6特性:包含es6的大部分特性,如箭头函数
- 是一种面向对象的语言:如类,接口,模块
- 可选的静态类型
- DOM操作
13,使用ts有什么好处
- 代码阅读性更好
- 调试简单:高级调试器专注于在编译之前捕获逻辑错误。
- 跨平台
14,ts的基本类型
- Number:let num1:number = 1;
- string:let str = “字符串”
- 布尔型:true||false
- null型:表示未定义的值
- any:任意类型
- unknown:类型安全的any
- [] || Array :数组类型
- 元组:元组类型用来表示已知元素数量和类型的数组。各个元素类型可以不同,但是位置必须相同
- enum:枚举类型用于定义数值集合 enum Color {“red”,“green”,“Blue"}
- void:用于表示方法的返回值类型,
- undefined:表示值未定义
- never:表示从不会出现的值
15,什么是any类型?在什么时候使用?
- any表示任何值,只要沾上了any就代表ts将不会对这个值进行类型检查。
- 当一个变量需要赋值的数据类型不确定时,可以使用any类型,他可以赋值任何类型
16,什么是void?适用于什么场景
- 以函数举例,当函数没有返回值的时候,可以适用void。注意不能将null 返回给void
17,在ts中,声明变量用哪些关键字
- type:只能声明一次
- interface:可以声明多次
- enum:声明一个枚举变量
- let const var
18,如何在ts中创建一个对象?
let obj:{x:number,y:string}={
x:1,
y:"字符串"
}
19,如何在ts中指定可选属性?
使用变量名+?:类型即可
20,说说枚举
enum枚举用来定义一组常量
21,说说ts中for循环的几种变体
- for(let i = 0;i<length;i++)
- array.forEach()
- for…of
22,接口(interface)和类型别名(type)的区别
-
接口基本使用
- 接口可以重名,可以合并,
- 用接口约束的对象 或者 类 要和接口里的一样,不能多 不能少。
interface yourType{ name:string, age:number } iterface yourType{ height:number } let you:yourType = { name:"***", age:12, height:175 }
-
类型别名基本使用
- 描述一个对象的类型
- 特点是:名称唯一 ,不能重复,实例化出来的对象属性不能多不能少。
-
区别:
- 接口名称可以重复,而type不可以
- 接口可以重复定义
- type可以使用in关键字生成映射类型,而接口不行
-
使用建议:优先使用interface,公用的使用interface,其次再用type
23,谈谈泛型和any的区别
- 相同点:都是用来定义一个未知类型的变量
- 不同点:
- any:ts将跳过对此变量的类型检查
- 泛型:不预先指定具体的类型,而是在使用的时候再使用来指定指定具体类型。
24,泛型的使用
-
在函数中使用
function echo<T>(arg:T){ return arg; }
-
在类中使用
class Animal<T>{ name:T; constructor(name:T){ this.name = name; } action<T>(say:T){ console.log(say); } }
-
在接口中使用
interface Animall<T,U>{ key:T, value:U }
25,ts中的类型断言是什么?
- 语法:
值 as 类型
他的意思是说,我认为这个值是某个类型,编译器 请跳过检查。 - 特点:联合类型可以断言为其中一个类型,父类可以断言为子类,任何类型都可以断言成any。
- 注意:类型断言只会影响ts编译时的类型,编译结果出来后,类型断言会被删除。
26,如何使用ts将字符串转换为数字,
- 使用parseInt
- 使用parseFloat
- 使用+ 号
+3
27,ts中的类是什么?
- 类表示一组相关对象的共享行为和属性
28,如何在node环境运行ts文件
安装ts-node, 然后使用命令ts-node fileName
29,解释rest参数和声明rest参数的规则
- 含义:其余参数允许你将不同数量的参数(零个或多个)传递给函数。
- 语法:
function (arg1:string, ...names:string[]){}
,表示剩余参数存在了names数组里 - 注意:rest参数必须是参数定义的最后一个,并且每个函数只能拥有一个rest参数
30,omit是什么?
- Omit允许你通过传递Type并选择Keys在新类型中省略来构造类型。Omit会构造一个除类型K外具有T性质的类型
- 语法:Omit<type,string>; 参数:第一个为继承的type类型,第二个为想要的key的字符串,多个字符串用|分开
- 简而言之,就是继承一个接口,然后过滤掉不想要的接口属性
31,如何实现函数重载
函数名相同,但参数类型或返回值不同的函数就是重载。两个函数必须接收相同数量的参数
32,如何让接口的所有属性都可选?
使用映射类型
-
语法:{ readonly [p in K] ?: T} //in 表示遍历,T表示ts中的任意类型
-
常见的类型语法:
1,{ [P in K] : T } // 默认不可选 2, { [P in K] ?: T} //全都是可选的 3,{ [P in K ] -?: T} // -号表示移除可选 ,这句的意思是把P都移除可选修饰符 4,{ readonly [P in K] : T} //全是只读的 5,{ readonly [P in K] ?: T} //添加只读修饰符 6,{ -readonly [P in K] ?: T} //移除只读修饰符
-
这题的答案应该是用{ [P in K ] ?: T}
33,ts中的模块指的是什么?
- 指的是相关变量,函数,类和接口的集合。
- 模块之间是用import引入,export来导出的。
CSS部分
1,什么叫做伪类,伪元素?都包括什么?
- 伪类(使用单冒号
:
):用来定义元素特殊状态的。如鼠标悬停,焦点样式,链接样式。举例:hover,active,link。 - 伪元素(使用双冒号
::
):新建的一个虚拟元素,他不存在于文档中。判断是否是伪元素就看他是不是新建的元素
2,回流,重绘
-
回流:元素的大小或者位置发生了改变,触发了 页面重新布局而导致渲染树重新计算布局或者渲染
- 改变窗口大小,
- 改变文字大小,
- 添加/删除样式表
- 用户输入
- 激活伪类等等
-
重绘:元素样式的改变(但宽高,大小,位置不变),只改变自身元素,不改变其他元素。包括:
- outline(设置元素轮廓),visibility(元素是否可见),color(颜色),background-color(背景色)
3,Animation和Transition 的区别是什么?
都是实现动画效果的,区别是,Animation可以定义动画关键帧,因此可以实现更复杂的动画效果。
4,媒体查询的使用方法:
- 语法:
@media 媒体类型 and (媒体特性){样式规则}
- 书写顺序:当使用
@media screen (min-width:xxxpx)
时,小分辨率要放在大分辨率上面,如先写768px,再写992,再写1440,如果是用max-width时,要先写大的,再写小的
5,响应式布局有哪些?简述一下这些响应式布局
- 百分比布局:缺点是需要按照设计稿,换成成百分比单位
- 媒体查询布局(@media):缺点是css代码量会增加很多,常用断点尺寸:576(small),>=576(sm) ,=>769(md),=>992(lg),=>1200(xl),=>1400(xxl)。实际开发中,使用栅格布局+断点设定实现响应式
- rem布局:
- rem是相对于html根元素的字体大小的单位
- 通过修改html中根元素字体大小,来控制rem的大小
- flexible.js插件可以实现。
- vw,vh响应式布局
- flex布局(不会脱离文档流),常用属性:
- felx-direction(主轴方向):row/row-reverse/column/column-reverse
- flex-wrap(是否换行):nowrap/wrap/wrap-reverse
- flex-flow(direction,wrap的简写):第一个参数是direction,第二个是wrap
- justify-content(主轴上对齐方式):flex-start/flex-end/center/space-between/space-around
- align-item(侧轴对齐):flex-start/flex-end/center/baseline(基线对齐)/stretch(拉伸)
- align-content(多轴对齐):flex-start/flex-end/center/space-between/space-around/stretch
- 项目属性(flex容器的子元素)
- order:子元素排序,数值越大越靠后
- flex-grow:子元素占领空间百分比,自动增长并填满空间
- flex-shrink:当父元素空间不够时进行缩小,数值越大,缩小的越多,0为不收缩
- flex-basis:子元素初始占据空间大小。
- flex(flex-grow,flex-shrink,flex-basis的简写):默认值0,1,auto
- align-self(单个子元素在侧轴上的对齐方式):auto/flex-start/flex-end/cener/baseline/stretch
6,canvas 常用api以及介绍
-
简介:canvas标签是一个图形容器,可以用js脚本来绘制图形。主要应用在动画,游戏画面,数据可视化,图片编辑,以及实时视频处理方面。
-
元素属性
属性名 含义 值 height canvas元素的高度 number width canvas元素的宽度 number getContext(“2d”) 获取canvas上下文 2d toDataURL(type, encoderOptions) 返回一个数据URL,该URL包含由类型参数指定的格式的图像(默认为png) encoderOptions在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量 toBlob(callback, type, encoderOptions) 回调函数,可获得一个单独的Blob对象参数 其余两个参数含义同上 -
线条相关(设定线条样式,偏移量,实线虚线的):
属性 描述 值 lineWidth 线的宽度 number lineCap 线末端的类型 butt,round,square lineJoin 两线相交拐点类型 miter,round,bevel miterLimit 斜切面限制比例 10 setLineDash([]) 设置当前的线段样式 数组里的值依次对应虚线的线段和空白的长度,依次重复 lineDashOffset(offset) 从哪里开始绘制线 -
绘制矩形
属性 描述 值 clearRect(x,y,width,height) 清除指定区域矩形 fillRect(x,y,width,height) 填充指定区域矩形 strokeRect(x, y, width, height) 使用当前的绘画样式(包括颜色等),描绘一个矩形 -
路径
属性 描述 值 beginPath() 开始一条路径,或重置当前的路径。 closePath() 使笔点返回到当前自路径的起始点 moveTo(x, y) 将一个新的子路径的起始点移动到指定坐标 lineTo(x, y) 链接到指定坐标,可以理解为画到哪里 arc(x, y, r, startAngle, endAngle, 是否逆时针) 绘制一段圆弧 arcTo(x1, y1, x2, y2, r) 绘制两个点之间半径为r的圆弧 rect(x, y, width, height) 绘制一个矩形,可以通过fill或者stroke来填充或描边 bezierCurveTo() 贝塞尔曲线 -
绘制路径
属性 描述 值 fill() 填充路径 stroke() 描边路径 clip() 将当前创建的路径设置为当前剪切路径的方法 -
填充和描边
属性名 作用 默认值 fillStyle 设置或返回用于填充绘画的颜色、渐变或模式。 strokeStyle 属性设置或返回用于笔触的颜色、渐变或模式。 -
渐变:返回的CanvasGradient对象的addColorStop(offset, color)添加渐变颜色
属性名 作用 默认值 createLinearGradient(x0, y0, x1, y1) 创建一个沿参数坐标指定的直线的渐变。该方法返回一个线性 对象 返回值可以作为描边或者填充的值使用 createRadialGradient(x0, y0, r0, x1, y1, r1) 确定两个圆的坐标,放射性渐变 -
图案:返回CanvasPattern对象,可以把此模式赋值给当前的fillStyle等,在 canvas 上绘制出效果
属性名 作用 默认值 createPattern(image, repetition) 用指定的图片创建图案 image可以是图片,视频,canvas的Element,或者canvas上下文,ImageData,Blob, ImageBitmap; repetition是重复方式,跟css里的背景图片重复参数一样 -
绘制文本
属性名 作用 默认值 fillText(text, x, y,[maxWidth]) 在指定位置填充绘制文本,最大宽度可选 strokeText(text, x, y,[maxWidth]) 在指定位置描边绘制文本,最大宽度可选 measureText(text) 返回TextMetrics 对象 -
文本样式
属性名 作用 默认值 font 设置字体 格式跟css的font一样 关于字体的样式都是在这里一起设置的 textAlign 文本对齐方式 start, end , left, right, center textBaseline 基线对齐方式 top, hanging, middle, alphabetic (默认),ideographic, bottom. direction 文本方向 ltr, rtl, inherit (默认) -
阴影
属性名 作用 默认值 shadowColor 阴影颜色 shadowBlur 阴影模糊程度 shadowOffsetX 阴影水平偏移量 shadowOffsetY 阴影垂直方向偏移量 -
变换
属性名 作用 默认值 rotate(deg) 坐标系顺势转旋转指定角度 scale(x, y) canvas每个单位添加缩放变换 translate(x, y) 对当前坐标系平移 transform() setTransform() resetTransform() -
合成
属性名 作用 默认值 globalAlpha 合成到canvas之前,设置图形和图像的透明度 globalCompositeOperation 设置如何在已经存在的位图上绘制图形和图像 详细用法 -
绘制图像
属性名 作用 默认值 drawImage() 绘制图像 ctx.drawImage(image, dx, dy); 或者ctx.drawImage(image, dx, dy, dWidth, dHeight); 或者 ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
-
像素控制文章来源:https://www.toymoban.com/news/detail-506098.html
属性名 作用 默认值 createImageData(width, height 或者 imagedata) 创建一个新的、空白的、指定大小的imageData对象 从现有的 ImageData 对象中,复制一个和其宽度和高度相同的对象。图像自身不允许被复制。 getImageData(sx, sy, sw, sh) 用来描述canvas区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为sw、高为sh putImageData() ctx.putImageData(imagedata, dx, dy);或 ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); -
canvas状态文章来源地址https://www.toymoban.com/news/detail-506098.html
属性名 作用 默认值 save() 使用栈保存当前的绘画样式状态,你可以使用 restore() 恢复任何改变 restore() 恢复到最近的绘制样式状态,此状态是通过 save() 保存到”状态栈“中最新的元素 canvas
到了这里,关于持续不断更新中... 自己整理的一些前端知识点以及前端面试题,包括vue2,vue3,js,ts,css,微信小程序等的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!