vue最新属性基于2.0略带3.0对比(基本知识)大全
// 监听键盘 @keydown 按下 @keyup 抬起 // 相关修饰符 .keycode 哪个键 .enter 操作回车键 .tab .delete .esc .space .left .right
vue 两大开发特点:响应式MVVM、组件化
// v-model 双向绑定原理(动态绑定一个value,然后监听一个@input 事件,在内部做响应的修改,通过$event.target.value) // 修饰符 v-model.lazy = '' 失去焦点后内容才跟着改变 v-model.number = '' 指定值的类型 v-model.trim = '' 过滤内容首尾的空格
// 指令 v-once 只渲染一次 v-text 替代显示对应的数据对象上的值 v-html 解析字符串内的标签或html写法 v-pre 不编译双大括号里的内容 v-cloak 数据解析前不显示 v-bind 简写 ‘ : ’ (多用作动态处理) v-on 简写‘ @ ’ (事件绑定)事件绑定后面不带() 可打印出事件对象,arguments 直接打印拿到所有参数 v-show 是否显示 v-if/v-else-if/v-else 用于判断 v-for 遍历数组或对象(对象的遍历属性值有key/item/index) // 2.0中v-for 优先于v-if 生效;3.0中v-if优先于v-for生效(同一元素避免同时使用这两个) // v-for的对象或数组值也可以是一个函数方法的rerun 值(例如常用的模糊查询效果),:key 值不要使用对象或数组之类的非基本类型,用字符串或数值类型的唯一性的值 // 绑定key值的好处:高效渲染更新dom,防止数据错位混乱,规避风险bug(采用Diff 算法)
// 默认事件 action <form action="http://www.baidu.com"> <input type="submit" value="提交"/> </form>
// 常用事件修饰符 // JS 执行代码 event.stopPropagation(); 阻止事件冒泡 event.preventDefault(); 阻止默认事件 // 修饰符 .stop 阻止事件冒泡 .prevent 阻止默认事件
// 动态绑定类 // 通过改变布尔值状态决定样式类是否生效 :class={样式类名称:布尔值}
// 计算属性 computed (本质是一个属性,需要通过计算得到) // 扩展理解:函数,全局定义的,属于window 的;方法,绑定在具体对象上的 // computed 这个属性底层有get 和set 两个方法,一般页面渲染调用get 方法,传值的时候才会调用set 方法 // 计算属性能做的,函数方法也都能做。但是如果一个属性只在页面调用1次,用计算属性或者方法都没区别,如果调用多次,函数方法就需要同时调用很多次,影响性能,而计算属性只调用1次即可缓存结果(也就是第一次运算将结果缓存,第二次运行会检查结果是否有变化,有变化重新计算结果缓存,没有就直接取缓存值) //在computed:{} 内定义的本质上还是属性,写法如函数 <div>{{ name }}</div> computed:{ name(){ return this.firstName+this.lastName } } // 简而言之就是页面显示的某个值,需要运算或是复杂处理后才能显示的,最好用计算属性 return 得到
// watch:{} 侦听器 和计算属性功能类似,是计算属性的底层实现原理 // 如果一个功能既可以用计算属性实现也可以用侦听实现建议用计算属性,因为更简洁 // 侦听器可监听data内所有属性值变化,例: watch:{ // carrent 现在值 prev 之前值 num(carrent,prev){ deep:true, // 监听对内部值的变化(深度监听) immediate:true, // 立即以表达式当前的值触发回调(非惰性) handler(){ // 方法表达逻辑 } } } // 有时会因为页面提前触发导致属性值没有获取到,从而页面报错,可以通过this.$nextTick(() => { // 函数方法执行 }) 缓冲 // watch 和 computed 属性的区别: // 1. 计算属性在调用时需要在模板中渲染调用,修改计算所依赖的元数据,watch 在调用时只需要修改元数据(watch 监听数据变化,计算属性访问数据结果) // 2. 计算属性默认深度依赖,watch默认潜度依赖(也就是假如数据是一个对象或数组,计算属性可以把数据的每一层都遍历到,而watch 只监听到这个对象或数组的变化,如果对象或数组下面还有的对象或数组就不会监听到,如果想要实现深度监听要添加deep:true) // 3. 计算属性适合做帅选,不可异步,watch适合执行异步或开销较大的操作
// 组件化 非所有应用都适合组件拆分,看具体业务能否解耦出来决定是否能拆分 // 组件分类:页面级(例:单页页面),业务上可复用的基础组件(例:头部、脚部...),与业务无关的独立组件(例:某个页面内的某个样式块) // 组件命名:中横线,驼峰(注意:非工程化开发时,使用大写组件名在HTML中不能被解析) // 组件作用域:全局,局部(只能用于挂载它的一个实例里面) // 全局组件在打包构建时会对没有使用的地方造成许多重复的JS 代码,vue3里添加了功能解决了以上问题,所以使用全局或局部组件一样,但通常还是使用局部组件 // 组件选项注册--- 工程化写法 components:{'buttCount':count} // 组件的基本使用方法---非工程化写法 // 引入组件 <div><buttCount /></div> // 注册 app.component('buttCount',{ data(){ return{ count:0 } }, template:`<button @click='count++'> 点击了{{ count }}次</button>` })
// 组件中的父子层级关系(父组件中注册的子组件,不要在示例中直接去使用,在谁里面注册,就在哪里使用) // 组件标签化用法---非工程化写法 <script type='tex/template' id="ID名"> <button @click="count++">点击了 {{count}} 次</button> </script> <template id="ID名"> <button @click="count++">点击了 {{count}} 次</button> </template> // 最后在HTML中使用组件(id名)即可 // 也可以直接 template:`<button @click="count++">点击了 {{count}} 次</button>` 这种模板字符串写入组件内容
// 为什么vue 中的data 是一个函数不能是对象? // 1. 这里涉及到堆区(存放引用数据类型)和栈区(存放简单数据类型) // 2. 空的对象会在堆区开辟一个空间,并标识一个唯一地址,对象名在栈区指向这个地址 // 3. 看两个对象是否 === 主要看这两个是否指向同一个堆区地址,因为实际项目中有很多组件需要复用,如果data是个对象,那么所有的复用组件中的值将都会是同一个堆空间,那么在一个组件中修改了值,那所有的组件值都会跟着变。但如果data是一个函数,每次都return 出对象值,那么每个组件中的值都是独立的
// 组件间通信 // 常用方式:props(多用于父子间传参),自定义事件(多用于父子间传参),消息订阅与发布(非父子间传递),VUEX(多用于某个值多个组件运用传递) // 子组件通过props 对象指定传递的变量名(规范写法必须定义类型)type:指定类型;required:是否为必传;default:默认值,例: props:{ name:{type:String,required:true,default:'tom'} } // 在父组件里引入子组件,通过在引入的子组件上动态绑定传参值(通过属性传参),例:传参name // 传值时非基础类型都要 ' : ' 动态传 // 在props 实例中定义的名字是驼峰形式,在HTML中属性传参时无法识别大写,所以用 '-' (中划线) 方式绑定属性 <child :name='fatherName'></child> // 当有多个值传递时,如果一个个绑定值比较繁琐,可以把值全部包在对象中(注意:对象的键值对名称要与props接收的值名称相对应,然后通过 v-bidn = '包裹的对象名' 传递,底层会自动解析),例: <child v-bind='{name:"jerry",sex:"女"}'></child> // props数据类型:String,Number,Boolean,Array,Object,Date,Function,Symbol,也支持自定义类型
// no-props(父组件向子组件传值,没有动态绑定,子组件内也没有通过props 接收的情况,值也可以顺利展示,这种情况就叫做 no-props),例: <child title='传递值'></child> // 这种多用于传递设置子组件样式 // 注意:这个只作用到子组件最外层,如果不想接收no-props 的值,可在子组件内设置属性 inheritAttrs:false (与props设置同级) // 如果子组件内有多个同级别的外层元素,那就不能接收no-props,如果想要接收,要在子组件中指定接收的外层元素上板顶v-bind='$attrs' 就可生效 // 如果指向接收某个传递值,需要在子组件中指定接收的外层元素上绑定 :自定义的名称='$attrs.info' // 如果想在生命周期或方法中拿到可以通过 console.log(this.$attrs.info) 获取
// 子组件调用父组件中的方法 // 父组件中绑定这个方法 // 这里的boxClick 不是一个事件,而是一个自定义事件,所以里面没有event 的相关数据,所以乳沟要接收子组件传参过来的值,直接在方法中接收 <child @boxClick='boxFunc'></child> boxFunc(val){ console.log(val,'子组件接收过来的值.....') } // 子组件中通过 $emit 触发父组件中的方法 <button @click='btnClick'>点击</button> btnClick(){ console.log('点击了....') this.$emit('boxClick') // 这里boxClick 就是父组件中的监听事件 // 如果需要传参:this.$emit('boxClick',传参值) // 传多个参数:this.$emit('boxClick',传参1,传参2,.....),但是这种方法不推荐,可以通过一个对象或数组统一传递接收 }
// 父子组件中的相互访问 // 1. 父组件访问子组件---$refs(vue3 将children 属性去掉了) // 1-1. 给引入的子组件绑定ref='属性名' // 1-2. this.$refs.属性名.子组件值 // 1-3. this.$refs.属性名.子组件方法调用 // 2. 子组件访问父组件---$parent(不建议使用,会破坏组件的封闭性,让子组件和父组件产生了耦合) // 2-1. 直接在子组件中 this.$parent.父组件值(方法不建议使用) // 3. 子组件访问根组件(也就是最外城的组件)值----$root // 3-1. 直接在子组件中 this.$root.根组件值
// 插槽 就是子组件中的提供给父组件使用的一个占位符,用<slot> 表示,父组件可以在这个占位符中填任何模板代码,填充的内容会替换子组件的<slot> 标签 // 基本例: // 1. 一个组件多个地方用,在组件里写一个<slot></slot>占位(可以给slot 标签内设定默认内容), // 2. 在父组件引入子组件时,例: <children> <button>我替换了slot 标签</button> </children> // 具名插槽(根据名字标识将值传到指定的插槽位置): // 1. 在组件中的<slot name='插槽名'></slot> // 2. 在父组件中引入子组件后: <children> <template v-slot:插槽名> <button>我是替换的内容</button> </template> </children> // 如果在众多插槽中没有名字的,该如何显示: // 加上default 就会去找没有名称,都放在这里 <template v-slot:default> <button>我是匿名插槽的展示内容</button> </template> // 作用域插槽(最大特点父组件要用子组件里的数据): // 1. 子组件: <slot :data="组件中要传的值"></slot> // 2. 父组件中引入子组件: // 2-1. v-slot后面的default这里,如果是具名插槽,这里就是插槽名 // 2-2. 这里的定义的参数名,就相当于拿到了子组件的整个slot <children v-slot:default="定义的参数名"> <span>{{定义的参数名.data}}</span> </children>
// 动态组件标签的使用 <component>< /component> // 1. 子组件正常引入 // 2. HMTL 中使用并绑定is属性 <component :is='变量名'>< /component> // 3. 这里的变量名,是data中的一个变量,后面的赋值为子组件名,也就是当data 的变量值是哪里个组件名,HTML中就显示哪个组件 // 4. 注意:失活的组件是不被缓存的,所以如果想要实现缓存,就用 keep-alive 组件包一下,例: <keep-alive> <component :is='变量名'>< /component> </keep-alive> // 总结:其实就是简化了不同组件之间v-if或者v-show 的效果,不同组件间根据场景切换
// 异步组件(在应用中,可能需要将应用分隔成小一些的代码块,并只在需要的时候才从服务器中加载一个模块),用defineAsyncComponent 注册异步组件,例:(非工程化写法)async-item 是组件名 app.component('async-item',vue.defineAsyncComponent(() => { return new Promise((resolve,reject) => { setTimeout(() => { resolve({ template:'组件内容' }) },3000), }) })
// vue 组件声明周期函数(在一个组件的生命周期范围内某一时刻会自动执行的函数),这里挑挑几个常用的说下,具体可以参考vue官网 // beforeCreate(){} 实例生成之前 // created(){} 实例生成之后 // beforeMounted(){} 组件内容被渲染到页面前 // mounted(){} 组件内容被渲染到页面后(此时拿到dom) // 1. 通过vue实例对象创建一个app ,里面填入选项,将app 挂载在对应的id:'app' 上 // 2.(init)实例挂载后,检查内部事件和生命周期,做初始化 beforeCreate 在此时调用 // 3. (init)初始化组件的组件和函数方法等,以及先关模板 created 在此时调用 // 4. (has'el')判断实例中是否有template ,如果有将编译,如果没有就会HTML对应的id='app' 中去找 beforeMounted 和 mounted 在此时调用 // 5. 当一个组件经历以上4个周期后就已经被挂载到页面中,接下来就处于一个运行状态,注意:以上生命周期只调用1次 // 6. 当处于运行中就会调用以下的生命周期 // beforeUpdate(){} 当数据发生变化时调用 // updated(){} 数据发生班花,页面也更新完毕后调用 // beforeUnMount(){} (销毁前)当实例失效时自动执行dom还在 // unmounted(){} 当时实例失效时,dom完全销毁 // errorCaptured(){} 全局组件错误汇总捕获(3个参数---err:错误;instance:错误来源;info:错误来源信息) // 注意:vue3.0中 $destroy 和 unmount 方法都不建议使用,这两个方法让用户手动更改单个实例的生命周期
// vue3.0 的动画封装: // 1. 将想要实现动画的标签放在<transition></transition>标签中 // 2. vue封装号了样式类(也可以在类里面使用自定义动画): // 进入类 .v-enter-from 进入从哪个地方来 .v-enter-active 进入过程的样式 .v-enter-to 进入到哪去 // 离场类 .v-leave-from .v-leave-active .v-leave-to // 封装的样式 v-:代表作用到所有包裹在transition 标签内的元素,让其产生动画效果,如果设置某一个不产生动画效果,给其添加 name 属性: <transition name='自定义名'> <div></div> </transition> // 此时如果将样式类的v- 替换成 自定义名- ,就会只让name为这个自定义名的元素产生动画效果 // 如果在项目中即要动画又要过渡,也可以同时使用实现,但如果两者事件差实现较大,系统会自动中和两个时间,如果想要以其中一个时间效果为主,给 transition 标签加 type 属性: // 这里的animation 以动画效果为主;如果 type='transition' 以过渡效果为主 <transition type='animation'></transition> // 如果不想用 type,也可以绑定 :duration='1000' 这种时间效果 // 1000=1秒(控制所有效果时长) // 也可以写成 :duration="{enter:3000,leave:1000}" ,设置进入和离开时长,在这个时间范围内以自身实现,超过的以这个设置时长为准 // 组件库 Animate.css (基于c3 的动画样式库) // 在使用这个样式库的时候,上面那6个封装好的样式类无法和组件库样式同时生效,此时可将上面6个类改写成: <transition enter-from-class='自定义的calss名' enter-active-class='自定义的calss名' enter-to-class='自定义的calss名' leave-from-class='自定义的calss名' leave-active-class='自定义的calss名' leave-to-class='自定义的calss名' > </transition> // 这里的自定义的class名,也可以是组件库样式类名称 // 使用JS 钩子调用动画(具体参考vue3.0官网中动画) // 参数:el(里面包裹的元素);done(方法,调用这个方法代表进入或离开完成后触发,调用才能进入到 after-enter 的方法) <transition @before-enter='方法名' // 参数 el($event) @enter='方法名' // 参数 el.done @after-enter='方法名' // 参数el @enter-cancelled='方法名' @before-leave='方法名' @leave='方法名' // 参数el,done @after-leave='方法名' @leave-cancelled='方法名' :css='false' // false时样式类不生效 > </transition> // 多元素无缝动画切换(transition 里面包裹的元素搭配 v-if 和 v-else 实现) // transition 添加 mode='out-in'(表示当前元素先离开,之后新元素进来)) // transition 添加 mode='in-out'(表示新元素先进入,完成后当前元素离开)) // 当页面一刷新就有动画效果,就给 transition 添加 appear 属性 // 多组件无缝切换动画 // 1. 利用动态模板组件 <component :is='data中的变量(赋值为注册的组件名)'></component> // 2. 利用方法判断变量赋值的组件名,动态切换 // 列表过渡动画 // 1. 使用<transition-group></transition-group> 包裹 // 2. 标签样式类和之前一样,被包裹的这一组就会作用到动画效果
// Mixin 混入(一个重复数据需要多个地地方使用,可以使用混入复用),例:(非工程化用法) const myMixin = {} // 创建一个mixin对象,里面可以放任何数据(例:data,methods....) mixins:[myMixin] // 在实例中引入(就相当于把data,methods...这些数据放在了实例内) // 注意:1. 如果实例中有data 或 methods ...等属性两者不会冲突覆盖,会自动合并,如果实例中data 或methods...等内部有相同的对应值,实例中的优先级高于Minxin 的 // 2. 对于vue 声明周期,两个都会执行,先执行mixin 内的,再执行实例中的 // 3. 当在mixin 中定义了单个的键值对的值(例如:age:10),是不能直接通过age获取的,因为age属于自定义属性,不会放在data 内,不是vue 内部的,vue 官方文档中指出,所有的自定义值都是绑定在实例上的,最终都挂载在 $options 上,一个组件所有的东西在实例完成后都会挂载在这,所以,这种自定义属性获取通过 this.$options.age // 4. 如果在实例内也定义了相同的自定义属性,默认还是以实例内的为主,如果想要以mixin 为准,可配置:(以age为例,非工程化写法) // 例:(通过配置决定使用哪个里面的属性) // app 是实例的id对应名,mixinVal 参数1 mixin内的值,appVal 参数2 实例内的值 app.config.optionMergeStrategies.age = (mixinVal,appVal)=>{ return mixinVal || appVal // 当mixin 内有值用mixin的,没有就用实例里的 }
// 自定义指令 // 全局自定义指令(非工程化用法) // 创建并使用自定义指令 foucs(el 表示作用到哪个元素上) <input v-focus/> // 页面一刷新input 就获取焦点 app.directive('focus',{ mounted(el){ el.focus() } }) // 局部自定义指令,同样是v-focus 为例(非工程化用法) <script> const 自定义名称={ focus:{ mounted(el){ el.focus() } } } </script> data平级别 directives:自定义名称 // 引入 // 或者直接写成 data平级别 directives:{ focus:{ mounted(el){ el.focus() } } } // 自定义指令内的生命周期3.0解说: // 1. created(新增)元素的attribute 或事件侦听器应用前调用 // 2. beforMount(相当于2.0的bind) // 3. mounted (相当于2.0的inserted) // 4. beforeUpdate(新增)元素本身更新前调用,很像组件生命周期 // 5. updated(相当于2.0的componentUpdated 以及 update,这两个3.0中已经移除) // 6. beforeUnmount(新增)与组件生命周期钩子类似,在卸载元素前调用 // 7. unmounted(相当于2.0的unbind)
// Teleport(传送)将要作用的元素标签被teleport 标签包裹 // 需求场景,例如蒙层 // to='body' 指被传送到哪个元素上,也可以是#id名 或者 .class名 <teleport to='bdy'> <div></div> </teleport>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构