当前位置: 首页 > 科技观察

10Vue开发技巧

时间:2023-03-13 12:42:04 科技观察

/deep/.el-checkbox{display:block;font-size:26px;.el-checkbox__label{font-size:16px;}}路由参数解耦通常在组件内部使用路由参数,大部分人会这样做:exportdefault{methods:{getParamsId(){returnthis.$route.params.id}}}在组件中使用$route会形成一个与其对应的路由高耦合,使得组件只能在某些特定的URL上使用,限制了其灵活性。正确的做法是通过props解耦constrouter=newVueRouter({routes:[{path:'/user/:id',component:User,props:true}]})。设置路由的props属性为true后,组件可以通过propsexportdefault{props:['id'],methods:{getParamsId(){returnthis.id}}}接收params参数,另外,还可以returnpropsconstrouter=newVueRouter({routes:[{path:'/user/:id',component:User,props:(route)=>({id:route.query.id})}]})文件:路由器。vuejs.org/zh/guide/es...功能组件功能组件是无状态的,不能被实例化,没有任何生命周期和方法。创建功能组件也很简单,只需在模板中添加功能声明即可。一般适用于只依赖于外部数据变化的组件。由于重量轻,渲染性能也会得到提升。组件需要的一切都通过上下文参数传递。它是一个上下文对象,具体属性见文档。这里的props是一个包含所有绑定属性的对象。功能组件:

{{item.title}}

{{item.content}}

父组件使用:importListfrom'@/components/List.vue'exportdefault{components:{List},data(){return{list:[{title:'title',content:'content'}],currentItem:''}}}文档:cn.vuejs.org/v2/guide/re...开发时修改样式渗透第三方组件样式很常见,但由于scoped属性的样式隔离,可能需要去掉scoped或创建新的样式。这些做法会带来副作用(组件样式污染,不够优雅),样式渗透只有在css预处理器中使用才会生效。我们可以使用>>>或/deep/来解决这个问题:/deep/.el-checkbox{display:block;font-size:26px;.el-checkbox__label{font-size:16px;}}watch高级使用1.立即执行当监视的属性发生变化时触发手表的。有时候,我们希望watch可以在组件创建后立即执行。可能想到的方法是在create生命周期调用一次,但是这种写法不够优雅,或许我们可以使用这个方法:exportdefault{data(){return{name:'Joe'}},watch:{name:{handler:'sayName',immediate:true}},methods:{sayName(){console.log(this.name)}}}监听对象时,watch无法触发对象的属性被改变。我们可以为它设置深度监控:exportdefault{data:{studen:{name:'Joe',skill:{run:{speed:'fast'}}}},watch:{studen:{handler:'sayName',deep:true}},methods:{sayName(){console.log(this.studen)}}}2.触发监听执行多个方法使用数组设置多项,包括字符串、函数、对象:exportdefault{数据:{name:'Joe'},观察:{name:['sayName1',函数(newVal,oldVal){this.sayName2()},{handler:'sayName3',immaediate:true}]},方法:{sayName1(){console.log('sayName1==>',this.name)},sayName2(){console.log('sayName2==>',this.name)},sayName3(){console.log('sayName3==>',this.name)}}}文档:cn.vuejs.org/v2/api/#wat...watch监控多个变量watch本身不能监控多个变量。但是我们可以通过计算属性将多个需要监控的变量返回给对象,然后监控这个对象,实现“监控多个变量”exportdefault{data(){return{msg1:'apple',msg2:'banana'}},计算:{msgObj(){const{msg1,msg2}=thisreturn{msg1,msg2}}},观察:{msgObj:{handler(newVal,oldVal){if(newVal.msg1!=oldVal.msg1){console.log('msg1ischange')}if(newVal.msg2!=oldVal.msg2){console.log('msg2ischange')}},deep:true}}}事件参数$event$event是事件的特殊变量object,在某些场景下可以为我们提供更多的复杂函数的可用参数。1.原生事件的行为与原生事件中的默认事件对象相同:exportdefault{methods:{inputHandler(msg,e){console.log(e.target.value)}}}2.自定义事件中的自定义事件在捕获子组件my-item.vue抛出的值的表现:exportdefault{methods:{customEvent(){this.$emit('custom-event','somevalue')}}}复制代码App.vue:exportdefault{方法:{customEvent(index,e){console.log(e)//'somevalue'}}}文档:cn.vuejs.org/v2/guide/ev…cn.vuejs.org/v2/guide/co…自定义组件二-waybindingcomponentmodel选项:允许自定义组件在使用v-model时自定义props和events默认情况下,组件上的v-model将使用value作为prop和input作为event,但是一些输入类型例如,单选按钮和复选框按钮可能希望为不同的目的使用价值道具。这些情况下的冲突可以通过使用模型选项来避免。input默认为双向绑定更新事件,可以通过$emitexportdefault{props:{value:{type:Boolean,default:false}},methods:{switchChange(val){this.$emit('input',val)}}}修改组件的model选项,自定义绑定变量和事件exportdefault{model:{prop:'num',event:'update'},props:{value:{type:String,default:''},num:{type:Number,default:0}},methods:{numChange(){this.$emit('update',this.num++)}}}文档:cn.vuejs.org/v2/api/#mod…Monitoring组件生命周期通常我们使用$emit来监控组件生命周期,父组件接收事件通知子组件:exportdefault{mounted(){this.$emit('listenMounted')}}父组件:其实还有一个简洁的方法,使用@hook来监听组件的生命周期,不用组件的任何更改。同样,created、updated等也可以使用这个方法。Programmaticeventlisteners例如,在页面挂载时定义一个定时器,当页面被销毁时需要清除定时器。这看起来不错。但是仔细看看this.timer唯一的作用就是能够在beforeDestroy中获取定时器序列号,除此之外没有任何用处。exportdefault{mounted(){this.timer=setInterval(()=>{console.log(Date.now())},1000)},beforeDestroy(){clearInterval(this.timer)}}尽可能最好仅生命周期钩子可以访问它。这不是一个严重的问题,但它可以被认为是碎片。我们可以通过$on或$once监控页面生命周期销毁来解决这个问题:exportdefault{mounted(){this.creatInterval('hello')this.creatInterval('world')},creatInterval(msg){lettimer=setInterval(()=>{console.log(msg)},1000)this.$once('hook:beforeDestroy',function(){clearInterval(timer)})}}使用这个方法后,即使我们创建了多个定时器也不影响效果。因为它们会在页面销毁后以编程方式自动清除。文档:cn.vuejs.org/v2/guide/co...手动挂载组件在一些需求中,手动挂载组件可以让我们的实现更加优雅。比如弹窗组件,理想的用法是使用命令式调用,就像elementUI的this.$message。这种实现不是在模板中传递状态转换,而是非常糟糕。先从最简单的例子说起:importVuefrom'vue'importMessagefrom'./Message.vue'//构造子类letMessageConstructor=Vue.extend(Message)//实例化组件letmessageInstance=newMessageConstructor()//$mount可以传入Selector字符串,表示挂载到选择器上//如果不传入选择器,会被渲染成文档外的元素,可以想象document.createElement()在内存中生成dommessageInstance.$mount()//messageInstance.$el获取dom元素document.body.appendChild(messageInstance.$el)实现一个简单的消息弹窗组件Message/index.vue://默认选项constDefaultOptions={duration:1500,type:'info',content:'这是提示信息!',}letmid=0exportdefault{data(){return{notices:[]}},methods:{add(notice={}){//name标识用于去除弹窗let_name=this.getName()//合并选项notice=Object.assign({_name},DefaultOptions,notice)this.notices.push(notice)setTimeout(()=>{this.removeNnotice(_name)},notice.duration)},getName(){return'ms??g_'+(mid++)},removeNotice(_name){letindex=this.notices.findIndex(item=>item._name===_name)this.notices.splice(index,1)}}}.wrap{position:fixed;top:50px;left:50%;display:flex;flex-direction:column;align-items:center;transform:translateX(-50%);}.message{--borderWidth:3px;min-width:240px;max-width:500px;margin-bottom:10px;border-radius:3px;box-shadow:008px#ddd;overflow:hidden;}.content{padding:8px;line-height:1.3;}.message.info{border-left:var(--borderWidth)solid#909399;background:#F4F4F5;}.message.success{border-left:var(--borderWidth)solid#67C23A;background:#F0F9EB;}.message.error{border-left:var(--borderWidth)solid#F56C6C;background:#FEF0F0;}.message.warning{border-left:var(--borderWidth)solid#E6A23C;background:#FDF6EC;}Message/index.js:importVuefrom'vue'importIndexfrom'./index.vue'letmessageInstance=nullletMessageConstructor=Vue.extend(Index)letinit=()=>{messageInstance=newMessageConstructor()messageInstance.$mount()document.body.appendChild(messageInstance.$el)}letcaller=(options)=>{if(!messageInstance){init(options)}messageInstance.add(options)}exportdefault{//returninstallfunctionforVue.useregistrationinstall(vue){vue.prototype.$message=caller}}main.js:importMessagefrom'@/components/Message/index.js'Vue.use(Message)使用:this.$message({type:'success',content:'成功消息提示',duration:3000})文档:cn.vuejs.org/v2/api/#vm-…outer>>>.el-checkbox{显示:堵塞;字体大小:26px;.el-checkbox__label{字体大小:16px;}}