2022全面升级!Vue3TS仿知乎专栏企业级项目 download:https:www。sisuoit。com3301。html 1。使用vuecli创建Vue3。0项目(js版本) 官方文件:https:cli。vuejs。orgzhguidecreatingaproject。htmlvuecreate 比如,随着人工智能的不断发展,机器学习变得越来越重要,很多人都开始学习机器学习。本文介绍了机器学习的基本内容。 检查vuecli的版本,确保vuecli的版本高于4。5。0。 vue版本 安装或升级您的vuecli npm安装gvuecli 创建 vue创建vue测试 开始 cdvue测试 npm运行服务 二、常用的组合API 1。设置 了解: Vue3。0中新增的一个配置项,其值是一个函数。 设置是所有组合API的表演舞台。 数据、方法等。在组件中使用的应该在设置中配置。 设置函数的两个返回值: 如果返回一个对象,则该对象中的属性和方法可以直接在模板中使用。(重点!) 如果返回渲染函数,您可以自定义渲染内容。(理解) 注意: 尽量不要和Vue2。x配置混用。 设置中的属性和方法可在Vue2。x配置中访问(数据、方法、计算。。。)。 但是您无法访问Vue2。x配置(数据、方法、计算。。。)在设置中。 如果有重名,安装程序优先。 Setup不能是异步函数,因为返回值不再是返回的对象,而是承诺,模板看不到返回对象中的属性。(后面也可以返回一个Promise实例,但是需要悬疑和异步组件的配合。) 某人的信息 姓名:{{姓名}} 年龄:{{年龄}} sayHello(由Vue3配置) 导出默认值{ 名称:应用程序, 这里只是对设置的一个测试。我们暂且不考虑响应性的问题。 setup(){ 数据 Let张三 假设年龄18岁 设a200 方法 函数sayHello(){ Alert(我的名字是{name},今年{age}岁。你好!) } 返回一个对象(常用) 返回{ 姓名, 年龄, 说你好, } } } 1。1安装时需要注意两点 安装程序的执行时间 在创建之前执行一次,这是未定义的。 设置参数 Props:值是一个对象,它包含:从组件外部传递过来的,由内部组件声明接收的属性。 Attr:值是一个对象,它包含:从组件外部传递过来但没有在props配置中声明的属性,相当于这个。attrs。 Slots:接收到的slot内容相当于这个。老虎机。 Emit:分发自定义事件的函数,相当于这个。emit。 上下文:上下文对象 2。参考函数 1。功能:定义一个响应数据。 2。语法:constxxxref(initValue) 创建一个包含响应数据的引用对象(简称ref对象)。 JS:xxx。value中的操作数据 正在读取模板中的数据:。不需要值,直接:{{xxx}} 3。备注: 接收的数据可以是基本类型或对象类型。 类型的基本数据:响应还是由Object。defineProperty()的get和set来完成。 4。vue3如何通过ref属性获取元素? 我是DIV 导入{ref,onMounted} 导出默认值{ setup(){ letboxref(null); onMounted((){ console。log(box。value) }); 返回{box} } } 5。Vue3的父组件调用子组件的方法 父组件 父页面 试验 导入{ 定义一个组件, 裁判, }来自‘vue’; 导出默认定义组件({ setup(){ constsonrefref(null); consthandleClick(){ sonref。value。song(); } return{sonRef,handleClick,} } }) 子组件 子页面 导入{ 定义组件 }来自‘vue’; 导出默认定义组件({ setup(){ constsong()alert(helloworld); 返回{ 宋,不忘回报 } } }) 某人的信息 姓名:{{姓名}} 年龄:{{年龄}} 作业类型:{{job。type}} 薪资:{{job。salary}} 修改人们的信息 从vue导入{ref} 导出默认值{ 名称:应用程序, setup(){ 数据 Letref(张三) 设年龄ref(18) letjobref({ 类型:前端工程师, 薪水:30K }) 方法 函数changeInfo(){ name。value李四 age。value48 console。log(作业。值) job。value。typeUIdesigner job。value。salary60K console。log(姓名,年龄) } 返回一个对象(常用) 返回{ 姓名, 年龄, 工作, changeInfo } } } 3。反应函数 函数:定义对象类型的响应数据(不要将其用于基本类型,使用ref函数) 语法:constProxyobjectreactive(源对象)接收一个对象(或数组)并返回一个代理对象(Proxy的实例对象,简称代理对象)。 reactive定义的响应式数据是深度的。 基于内部ES6的代理实现通过代理对象操作源对象的内部数据。 某人的信息 姓名:{{person。name}} 年龄:{{person。age}} 作业类型:{{person。job。type}} 薪资:{{person。job。salary}} 爱好:{{person。hobby}} 测试数据c:{{person。job。a。b。c}} 修改人们的信息 从vue导入{reactive} 导出默认值{ 名称:应用程序, setup(){ 数据 让人被动({ 姓名:张三, 年龄:18, 工作:{ 类型:前端工程师, 工资:30K, 答:{ 乙:{ 丙:666 } } }, 爱好:〔抽烟,喝酒,烫发〕 }) 方法 函数changeInfo(){ Person。name李四 人。年龄48 Person。job。typeUIdesigner person。job。salary60K person。job。ab。c999 Person。hobby〔0〕学习 } 返回一个对象(常用) 返回{ 人, changeInfo } } } 4。VUE3。0中的回应原则 4。1vue2。x的响应 1。实施原则: 类型:通过Object。defineProperty()拦截属性的读取和修改(数据劫持)。 数组类型:通过重写一系列更新数组的方法来实现拦截。(改变数组的方法是包装好的)。 Object。defineProperty(data,count,{ get(){}, set(){} }) 2。存在的问题: 添加或删除属性,界面不会更新。 通过下标直接修改数组,界面不会自动更新。 仿真Vue2中响应的实现 源数据 letperson{ 姓名:张三, 年龄:18岁 } Object。defineProperty(p,name,{ 可配置:真, 当有人读名字时调用Get(){函数 返回人员姓名 }, Set(value){当有人修改名称时调用 console。log(‘有人修改了name属性,我发现了。我要更新界面了!) person。name值 } }) Object。defineProperty(p,age,{ Get(){当有人读取年龄时调用 返回person。age }, Set(value){当有人修改年龄时调用 console。log(‘有人修改了年龄属性,我发现了。我要更新界面了!) 人。年龄价值 } }) 4。2响应4。2Vue3。0 1。实施原则: 通过代理:拦截对象中任意属性的变化,包括读写属性值、添加属性、删除属性等。 通过反射:对源对象的属性进行操作。 MDN文档中描述的代理和反射: 代理:https:developer。mozilla。org。。。 反射:https:developer。mozilla。org。。。 2。模拟Vue3中的响应 源数据 letperson{ 姓名:张三, 年龄:18岁 } constp新代理(person,{ 当有人读取p的一个属性时调用。 get(目标,属性名){ Console。log(有人读取了P上的{propName}属性) 返回Reflect。get(目标,属性名) }, 当有人修改或将属性追加到p时调用。 set(目标,属性名,值){ Console。log(有人修改了p上的{propName}属性,我要更新界面了!) Reflect。set(目标,属性名,值) }, 当有人删除p的一个属性时调用。 deleteProperty(target,propName){ Console。log(有人删除了p上的{propName}属性,我要更新界面了!) 返回Reflect。deleteProperty(目标,属性名) } }) 5。电抗与基准电压的关系 1。从定义数据的角度进行比较: Ref用于定义:基本类型数据。 Reactive用于定义:对象(或数组)类型数据。 注意:ref也可以用来定义对象(或数组)类型数据,其内部会通过reactive自动转换为代理对象。 2。从原理角度比较: 响应(数据劫持)是通过Object。defineProperty()的get和set实现的。 Reactive通过使用代理实现responsive(数据劫持),通过Reflect操作源对象内部的数据。 3。从使用角度比较: 引用定义的数据:。值是操作数据所必需的,但是。读取数据时,模板中的直接读取不需要值。 反应式定义数据:运行数据和读取数据:不需要。价值。 7。计算属性和监控 7。1。计算函数 与Vue2。x中computed的配置功能一致 写作方法 某人的信息 姓氏: 名称: 全名:{{person。fullName}} 全名: 从vue导入{反应式,计算式} 导出默认值{ 名称:演示, setup(){ 数据 让人被动({ 名字:张, 姓氏:三 }) 计算属性速记(不考虑计算属性的修改) person。fullnamecomputed((){ 返回person。firstnameperson。lastname }) 计算属性全写(考虑读写) person。fullNamecomputed({ get(){ 返回person。firstnameperson。lastname }, 设置(值){ constnameArrvalue。split() person。firstNamenameArr〔0〕 person。lastNamenameArr〔1〕 } }) 返回一个对象(常用) 返回{ 人 } } } 7。2。手表功能 1。与Vue2。x中的手表配置功能一致 2。两个小坑: 在监控reactive定义的响应式数据时:oldValue无法正确获取,强行开启深度监控(深度配置失败)。 当监控由reactive:deep配置定义的响应数据中的属性时,该配置有效。 3。写作方法 当前总和为:{{sum}} 点1 当前信息是:{{msg}} 修改信息 姓名:{{person。name}} 年龄:{{person。age}} 薪资:{{person。job。j1。salary}}K 修改名称 成长年龄 涨薪 从vue导入{ref,reactive,watch} 导出默认值{ 名称:演示, setup(){ 数据 让sumref(0) Letmsgref(Hello) 让人被动({ 名字:小叮当, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) 情况1:监控ref定义的响应数据 手表(总和,(新值,旧值){ Console。log(sumchanged,newValue,oldValue) },{immediate:true}) 情况2:监控ref定义的多个响应数据 手表(〔sum,msg〕,(newValue,oldValue){ Console。log(sum或msg已更改,新值,旧值) },{immediate:true}) 案例3:监控由reactive定义的响应数据的所有属性。 1。注意:此处无法正确获取旧值。 2。注意:深度监控是强制开启的(深度配置无效) 手表(人,(新值,旧值){ Console。log(人员已更改,新值,旧值) },{deep:false})此处的深度配置无效。 情况4:监控reactive定义的响应数据中的一个属性。 手表(()person。name,(newValue,oldValue){ Console。log(人名已更改,新值,旧值) }) 情况五:监控reactive定义的一个响应式数据中的一些属性。 watch(〔()person。name,()person。age〕,(newValue,oldValue){ Console。log(姓名或年龄已更改,newValue,oldValue) }) 特殊情况 手表(()person。job,(newValue,oldValue){ Console。log(人员的工作已更改,新值,旧值) },{deep:true}) 在这里,深度配置是有效的,因为它监视由反应性元素定义的对象中的一个属性。 返回一个对象(常用) 返回{ 总和, 味精, 人 } } } 7。3。watchEffect功能 1。watch的套路是:既要指明被监控的属性,又要指明被监控的回调。 2。watchEffect的套路是:不需要指明要监控哪个属性,监控的回调中使用了哪个属性,那么就可以监控哪个属性。 3。watchEffect有点像computed: 但是computed注重的是计算值(回调函数的返回值),所以需要写返回值。 WatchEffect更注重过程(回调函数的函数体),所以不需要写返回值。 总和:{{sum}} 点1 当前信息:{{msg}} 修改 姓名:{{person。name}} 年龄:{{person。age}} 薪资:{{person。job。j1。salary}}K 修改名称 成长年龄 涨薪 从vue导入{ref,reactive,watch,watchEffect} 导出默认值{ 名称:演示, setup(){ 数据 让sumref(0) Letmsgref(Hello) 让人被动({ 姓名:张三, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) 监控 watch(sum,(newValue,oldValue){ console。log(sum的值已更改,newValue,oldValue) },{immediate:true}) watchEffect((){ 常数x1sum。value constx2person。job。j1。salary Console。log(执行了watcheffect指定的回调) }) 返回一个对象(常用) 返回{ 总和, 味精, 人 } } } 8。生存期 生命周期图 1。在Vue3。0中可以继续使用Vue2。x中的生命周期钩子,但是其中两个已经被重命名了: BeforeDestroy被重命名为beforeUnmount。 已销毁被重命名为已卸载。 2。Vue3。0还以CompositionAPI的形式提供了生命周期钩子,与Vue2。x中钩子的对应关系如下: beforeCreate设置() 已创建安装程序() beforeMountonBeforeMount 已安装已安装 beforeUpdateonBeforeUpdate 更新未更新 beforeunmountonBeforeUnmount 未安装未安装 当前总和为:{{sum}} 点1 从vue导入{ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} 导出默认值{ 名称:演示, setup(){ console。log(setup) 数据 让sumref(0) 使用复合API形式的生命周期挂钩 onBeforeMount((){ console。log(onBeforeMount) }) onMounted((){ console。log(onMounted) }) onBeforeUpdate((){ console。log(onBeforeUpdate) }) 未更新((){ console。log(onUpdated) }) onBeforeUnmount((){ console。log(onBeforeUnmount) }) 未安装((){ console。log(onUnmounted) }) 返回一个对象(常用) 返回{sum} }, 以配置项的形式使用生命周期挂钩 区域 创建之前(){ console。log(beforeCreate) }, 已创建(){ console。log(created) }, beforeMount(){ console。log(beforeMount) }, 已安装(){ console。log(mounted) }, 更新之前(){ console。log(更新前) }, 已更新(){ console。log(已更新) }, 卸载之前(){ console。log(beforeUnmount) }, 卸载(){ console。log(已卸载) }, 结束区域 } 9。自定义挂钩功能 1。钩子是什么?本质是一个函数,封装了setup函数中使用的CompositionAPI。 2。类似于vue2。x中的mixin 3。自定义钩子的优点:复用代码,使设置中的逻辑更加清晰易懂。 4。演示。vue 当前总和为:{{sum}} 点1 在当前点击时,鼠标的坐标是:x:{{point。x}},y:{{point。y}} 从vue导入{ref} 从导入使用点。。hooksusePoint 导出默认值{ 名称:演示, setup(){ 数据 让sumref(0) 设pointusePoint() 返回一个对象(常用) 返回{sum,point} } } 5、hooksusePoint。js 从vue导入{reactive,onMounted,onBeforeUnmount} 导出默认函数(){ 鼠标打点的相关数据 letpointreactive({ x:0, y:0 }) 与鼠标打点相关的方法 函数保存点(事件){ point。xevent。paxx point。y事件。页面 console。log(event。pageX,event。pageY) } 实现鼠标打点相关的生命周期钩子 onMounted((){ window。addEventListener(click,保存点) }) onBeforeUnmount((){ window。removeeventlistener(click,保存点) }) 返回点 } 10。托雷夫 1。角色:创建一个ref对象,其值指向另一个对象中的一个属性。 2。语法:constnametoRef(person,name) 3。应用:当响应对象中的一个属性只供外部使用时。 4。扩展:torefs的功能和toRef一样,但是可以批量创建多个Ref对象。语法:toRefs(person) {{person}} 姓名:{{姓名}} 年龄:{{年龄}} 薪资:{{job。j1。salary}}K 修改名字 年龄增长 升上人生巅峰。 从vue导入{ref,reactive,toRef,toRef} 导出默认值{ 名称:演示, setup(){ 数据 让人被动({ 姓名:张三, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) constname1person。name console。log(,name1) constname2toRef(person,name) console。log(。。。),名称2) constxtoRefs(人) console。log(,x) 返回一个对象(常用) 返回{ 人, name:toRef(person,name), age:toRef(person,age), 薪金:toRef(person。job。j1,薪金), 。。。斗牛士(人) } } } 三。其他成分API 1。浅层无功和浅层参考 1。shallowReactive:只处理对象最外层属性的响应(浅层响应)。 2。shallowRef:只处理基本数据类型的响应,不处理对象的响应。 3。什么时候用? 如果有一个对象数据,结构是深的,但当它发生变化时,只是外层属性的变化shallowReactive。 如果有一个对象数据,后续函数不会修改对象中的属性,而是创建一个新的对象来替换shallowRef。 的当前x。y值为:{{x。y}} 单击我替换x 点我x。y {{person}} 姓名:{{姓名}} 年龄:{{年龄}} 薪资:{{job。j1。salary}}K 修改名称 成长年龄 涨薪 从vue导入{ref,reactive,toRef,toRef,shallowReactive,shallowRef} 导出默认值{ 名称:演示, setup(){ 数据 letpersonshallowreactive({只考虑第一层数据的响应。 让人被动({ 姓名:张三, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) 设xshallowRef({ y:0 }) console。log(,x) 返回一个对象(常用) 返回{ x, 人, 。。。斗牛士(人) } } } 2。只读和浅只读 1。readonly:将响应数据设为只读(深度只读)。 2。shallowReadonly:将响应数据设为只读(浅只读)。 3。应用场景:不希望数据被修改的时候。 当前总和为:{{sum}} 点我吧 姓名:{{姓名}} 年龄:{{年龄}} 薪资:{{job。j1。salary}}K 修改名称 成长年龄 涨薪 从vue导入{ref,reactive,toRefs,readonly,shallowReadonly} 导出默认值{ 名称:演示, setup(){ 数据 让sumref(0) 让人被动({ 姓名:张三, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) personreadonly(person) personshallowreadonly(person) sumreadonly(总和) sumshallowReadonly(sum) 返回一个对象(常用) 返回{ 总和, 。。。斗牛士(人) } } } 3。托拉和马克劳 1、托拉: 功能:将reactive生成的一个响应对象变成一个正常对象。 使用场景:用于读取响应对象对应的普通对象。对这个普通对象的所有操作都不会导致页面更新。 2、markRaw: 角色:标记一个对象,使其永远不再是响应对象。 应用场景: 有些值不应该设置为响应式,比如复杂的第三方类库。 当呈现具有不可变数据源的大型列表时,跳过响应转换可以提高性能。 当前总和为:{{sum}} 点我吧 姓名:{{姓名}} 年龄:{{年龄}} 薪资:{{job。j1。salary}}K 汽车信息:{{person。car}} 修改名称 成长年龄 涨薪 输出原人物。 给人加个车。 更改汽车的名称 改变价格 从vue导入{ref,reactive,toRefs,toRaw,markRaw} 导出默认值{ 名称:演示, setup(){ 数据 让sumref(0) 让人被动({ 姓名:张三, 年龄:18, 工作:{ j1:{ 工资:20英镑 } } }) 函数showRawPerson(){ constptoRaw(人) p。age 控制台。log(p) } 函数addCar(){ 汽车{名称:奔驰,价格:40} person。carmarkRaw(汽车) } 函数changePrice(){ person。car。price console。log(person。car。price) } 返回一个对象(常用) 返回{ 总和, 人, 。。。toRefs(人), showRawPerson, addCar, 改变价格 } } } 4。customRef 1。功能:创建自定义ref,并显式控制其依赖跟踪和更新触发器。 2。达到防抖效果: {{keyWord}} 从vue导入{ref,customRef} 导出默认值{ 名称:应用程序, setup(){ 自定义一个名为:myRef的ref 函数myRef(值,延迟){ 让计时器 returncustomRef((track,trigger){ 返回{ get(){ Console。log(有人从这个容器myRef中读取了数据,我给了他{value}) Track()通知Vue跟踪值的变化(提前和get商量,让他觉得这个值有用) 返回值 }, set(newValue){ Console。log(有人将容器myRef中的数据更改为:{newvalue}) 清除超时(定时器) timersetTimeout((){ 值新值 Trigger()通知Vue重新解析模板。 },延迟) }, } }) } letkeyWordref(hello)使用Vue提供的ref Letkeywordmyref(hello,500)使用程序员定义的ref 返回{keyWord} } } 5。提供和注射 流程图 1。功能:实现祖先和后代组件之间的通信。 2。例程:父组件有一个提供选项来提供数据,子组件有一个注入选项来开始使用数据。 3。具体写法: 祖先组件: setup(){ 。。。。。。 Carreactive({name:奔驰,价格:40万}) 提供(汽车,汽车) 。。。。。。 } 在后代组件中: 设置(道具、上下文){ 。。。。。。 constcarinject(汽车) 返回{汽车} 。。。。。。 } 6。响应数据的判断 Is:检查一个值是否是ref对象。 IsReactive:检查对象是否是由Reactive创建的响应代理。 Readonly:检查对象是否是由readonly创建的只读代理。 IsProxy:检查对象是否是由reactive或readonly方法创建的代理。 setup(){ 汽车无功({名称:奔驰,价格:40W}) 让sumref(0) 让car2readonly(汽车) console。log(isRef(sum)) console。log(isReactive(car)) console。log(isReadonly(car2)) console。log(isProxy(car)) console。log(isProxy(sum)) 返回{。。。toRefs(汽车)} } 四。新组件 1。碎片 1。在Vue2中:组件必须有一个根标签。 2。在Vue3中:组件可以没有根标签,一个片段虚拟元素中会包含多个标签。 3。好处:减少标签级别和内存占用。 2。传送 什么是瞬间移动?Teleport是一种可以将我们组件的html结构移动到指定位置的技术。 我是一个弹出窗口。 关闭弹出窗口 3。焦虑 1。在等待异步组件的同时呈现一些额外的内容,让应用程序有更好的用户体验。 2。使用步骤: 异步引入组件 从vue导入{defineAsyncComponent} constChilddefineeasynccomponent(()import(。componentsChild。vue)) 用暂记包装组件,并配置默认和回退。 我是一个应用组件 装货。。。。。 动词(verb的缩写)其他人 1。全球API转移 1。Vue2。x有很多全局API和配置。 例如,注册全局组件、注册全局指令等。 注册全局组件 Vue。component(MyButton,{ 数据:()({ 计数:0 }), 模板:点击了{{count}}次。 }) 注册全局指令 Vue。directive(focus,{ inserted:elel。focus() } 2。这些API在Vue3。0中进行了调整: 将全局API,即Vue。xxx,调整到应用实例(app)。 2。x全局API(vue)3。x实例API(app) vue。config。xxxxapp。config。xxxx vue。config。production已删除提示 组件应用程序 指令 vue。misinapp。mixin vue。useapp。use vue。prototypeapp。config。globalproperties 2。其他变化 1。数据选项应该始终声明为函数。 过多的类名更改: 。回车, 。v离开到{ 不透明度:0; } 。v离开, 。venterto{ 不透明度:1; } Vue3。x写作 。venterfrom, 。v离开到{ 不透明度:0; } 。v离开离开, 。venterto{ 不透明度:1; } 3。去掉keyCode作为von的修饰符,同时不再支持config。keyCodes。 4。删除von。native修饰符 父组件中的绑定事件 在子组件中声明自定义事件。 导出默认值{ 发出:〔close〕 } 5。拆下过滤器。 Filter虽然这个看起来很方便,但是需要一个自定义的语法来打破花括号里的表达式只是JavaScript的假设,这不仅有学习成本,还有实现成本!建议用方法调用或计算属性替换筛选器。