vue使用总结
栏目: JavaScript · 发布时间: 5年前
内容简介:从以下几个方面整理:以上 main.js 中也可以通过 Vue.use 注册,其实实质还是调用 Vue.Component,对应的 use 的需要有一个 install 函数,使用 Vue.use 将触发 install 执行,然后在 install 中执行 Vue.component 操作。a.vue 和 b.vue,引用 bus.js ,Bus 为同一个实例,并不会重复创建,bus.js 就相当于一个调度中心,可以无数个组件,都和它建立链接,发布事件,然后 bus 将发布到给每一个建立链接的组件。
使用心得
从以下几个方面整理:
- vue 用法
- vue-router 用法
- webpack 打包
- 遇到的坑
Vue 用法
- 通常写的 .vue 文件,实则是在写 vue 的配置文件,最终将执行 new Vue() 的操作,传入这些配置。
new Vue({ data(){ return { name:'xx' } } }) // 常编写的.vue文件 export default { data(){ return { name:'xx' } } }
- 常用组件可以在全局注册。
- 组件代码,TestComp.vue
<template> <div> test component </div> </template> <script> export default {} </script>
- 注册组件,Vue.component 注册
// main.js import Vue from 'vue'; import TestComp from './TestComp.vue' Vue.component('test-comp',TestComp);
以上 main.js 中也可以通过 Vue.use 注册,其实实质还是调用 Vue.Component,对应的 use 的需要有一个 install 函数,使用 Vue.use 将触发 install 执行,然后在 install 中执行 Vue.component 操作。
// my-components.js import TestComp from './TestComp.vue' export default { install(Vue){ Vue.component('test-comp',TestComp) // 这里还可以有多个注册 vue.component vue.directive, vue.filter 等 } } // main.js import Vue from 'vue'; import MyComponents from './my-components.js'; Vue.use(MyComponents)
- 用的比较多的指令,过滤器,mixin,可以在全局配置
/* 1、 注册指令 */ Vue.directive('') /* 2、注册过滤器 */ Vue.filter('filterName',(val,...args)=>{ console.log(args); return val; }) // 过滤器使用 {{ 'abc' | filterName(1,2,3) }} // value = 'abc' args 为 [1,2,3] /* 3、全局 mixin (不建议) */ Vue.mixin({ mounted(){ console.log('每个组件中都将执行这里') } })
- keep-alive 的使用,可以缓存组件,可以通过 exclude 排除不需缓存的组件,include 包含需要缓存的,max 定义最大缓存的组件数。exclude,include 传入一个数组,元素对应组件的 name 属性,max 传入数字。
<keep-alive :incude="['home','list']" :max="3"> <router-view></router-view> </keep-alive>
- 在页面跳转时,新打开的页面滚动条可能缓存了滚动条位置,在中间的位置,进入页面或者在路由钩子的 afterEach 中执行 window.scroll(0,0) 重置到顶部。
- 非直接父子组件之间的通信,使用一个空 vue 对象实现通信。
// Bus.js import Vue from 'vue' export const Bus = new Vue() // a.vue import Bus from './bus.js' Bus.$emit('event_add_cart',1) // b.vue import Bus from './bus.js' Bus.$on('event_add_cart',(num)=>{ this.cartNum += num })
a.vue 和 b.vue,引用 bus.js ,Bus 为同一个实例,并不会重复创建,bus.js 就相当于一个调度中心,可以无数个组件,都和它建立链接,发布事件,然后 bus 将发布到给每一个建立链接的组件。
- computed 只有在依赖的 data 里面的值改变时,才会改变,优于直接在模板里执行表达式和方法,因为模板中的方法和模板,在每次 Vue 刷新视图时,都将重新执行一遍。
- data 需要是一个函数返回一个对象,如果直接赋值一个对象时,做不到隔离同一个组件的数据效果,都将公用同一份数据。
- 在 vue 组件销毁(beforeDestroy)前,清理定时器和 DOM 事件绑定。
- 在循环中使用 key,提升渲染性能,key 尽量不用数组下标,有 key 则 diff 算法就比较 key 值,最大程度上使用原组件,而不是销毁原来的组件后重建。
- v-for 可以和 v-if 同时使用,先循环再判断,所以可以有选择的渲染数组中的元素,而 angular 中是不支持同一个标签上同时存在 for 和 if 指令的。可能 eslint 会提示报错不建议混合使用,eslint 建议使用改变数组源数据的方式来实现,可以在 computed 中使用数组的 filter 过滤掉不想要的数据。
- 模板中 template 的使用,当几个同级的元素,需要依赖同一个指令时,又不想添加额外的标签将这些元素包裹时,可以使用 template,template 将不会渲染。在 template 使用 v-for 时,key 值需要添加在子元素上。
<template> <div> <template v-for="(item,index) in [1,2,3]"> <div :key="index"> {{item}} </div> </template> <template v-if="2>1"> <div> 2大于1 </div> <div> 2>1 </div> </template> </div> </template>
- 在 data 初始化时,对象类型的数据类型,如果不给初始化,单独改变值时,页面是不会响应该值的变化的。
<template> <div> {{info.name}} {{info.age}} <div v-for="(item,index) in arr" :key="index">{{item}}</div> </div> </template> <script> export default { data(){ return { info:{ age:1 }, arr:[], } }, mounted(){ this.info.name = 'xx'; // 并不能触发页面更新 this.info.age = 2; // 这样子可以触发页面更新 this.info = {name:'xx'}; // 这样子可以触发页面更新 // 数组同理 this.arr[0] = 1; // 并不能触发页面更新 this.arr = [1]; // 这样子可以触发页面更新 } } </script>
因为 Vue 在初始化时需要对 data 进行使用 defineProperty 进行 set 和 get 的劫持,如果对象中的值为空,那就不会存在相应的 set 和 get,所以两者方式,一个给对象里面设置初值,二个将对象改为一个新对象,而不是直接在上面添加属性和值。
基于以上,还有一个使用技巧,则是,一些表单如果依赖后台返回的一些数据初始化选择列表等,那么可以在赋值前,先在返回的数组中,加上一个属性,例如 isChecked,然后再赋值给 data
<template> <div> <template v-for="(item,index) in checkboxs"> <input type="checkbox" v-model="item.isChecked" :key="index"> </template> </div> </template> <script> export default { data(){ return { checkboxs:[] } }, methods:{ getData(){ // 请求过程略 let data = [{name:'zs',name:'ls'}] // 原请求返回数据 this.checkboxs = data.forEach(item=>Object.assign(item,{isChecked:false})) } } } </script>
- 开发组件时,可以用 slot 占位,内容在使用组件的地方填充,使组件更加灵活。
- 在开发管理后台时,可以将通用的数据和方法,写在 mixin 里面,然后在页面中注入,如通用表格的页码配置数据,加载中状态值,还有获取上一页,下一页的方法。
- 在查看大图的场景中,点开大图,安卓物理键返回时,需要关闭大图,而不进行页面的跳转,则是可以在点开大图的时候,pushState 在 history 中添加一个路由,如果页面需要点击关闭的功能,则需要在点关闭按钮时,手动触发 history.go(-1) 一下;
- 如果在例如一个操作结果页(比如支付完成),然后又不能手动配置分享内容的时候,又需要分享的是购买的商品时,则可以通过 replaceState 方法改变路由,但是又不会触发页面刷新,再分享时,app或者浏览器则会自动抓取到替换后的地址分享出去了。
- 父组件可以通过 @hook:created @hook:mounted 等监听到子组件的生命周期。
- errorCaptured 捕获子孙组件的错误。
-
slot 插槽的使用
- 匿名插槽
// child.vue <template> <header> <slot>all header</slot> </header> </template> // parent.vue <template> <child> <div>this is custom header</div> </child> </template>
> slot 中可以有默认值 - 具名插槽 ```vue // child.vue <template> <header> <slot name="left">left</slot> <slot name="right">right</slot> </header> </template> // parent.vue <template> <child> <div slot="left">custom left</div> <div slot="right">custom right</div> <div slot="right">custom right2</div> </child> </template> ``` > 具名插槽可以有一个以上同样 name 的填充。注意组件中用 slot + name ,使用时用 slot=name ,这里容易搞混。 - 带值传递插槽,slot-scope,也就是子组件的值传递给父组件 ```vue // child.vue <template> <header> <slot :user="userinfo" :address="address"></slot> </header> </template> <script> export default { data() { return { userinfo: { name: 'haokur' }, address: { city: 'guangzhou' }, } }, } </script> // parent.vue <template> <div> <Child> <template slot-scope="row"> {{JSON.stringify(row)}} => {"user":{"name":"haokur"},"address":{"city":"guangzhou"}} </template> </Child> </div> </template> ``` - 带值传递插槽的使用场景,在 element-ui 中使用的较多,当在非父组件中的循环时,而是向子组件传递值,子组件去遍历时,父组件中的插槽无法拿到遍历的当前值,需要子组件在遍历的时候,把值又给附加在 slot 上。 ```js // List.vue <template> <ul class="table"> <li class="row" v-for="(item,index) in dataList" :key="index"> <slot :row="item"> {{item}} </slot> </li> </ul> </template> <script> export default { props: ['dataList'], } </script> /// parent.vue <template> <div> <TestList :dataList="[1,2,3,4,5,6]"> <template slot-scope="scope"> {{ scope.row * 2 }} </template> </TestList> </div> </template> ``` > 于是就实现了,子组件反向又像父组件传递值
- v-once 进行渲染优化,v-once 只会初始化一次,之后页面数据发生变化,v-once 内的内容也不会发生变化。
<template> <div> <span v-once>{{dateNow}}</span> <span>{{dateNow}}</span> </div> </template> <script> export default { data(){ return { dateNow: Date.now() } }, mounted(){ setInterval(() => { this.dateNow = Date.now() }, 1000) } } </script>
测试可看到只有没有加 v-once 的时间在变。
- 关于在 created 还是在 mounted 生命钩子里发送数据请求。有些说法是放在 created 中会好一些,可以避免多渲染一次?其论据可能是数据如果加载得快,那么就不render默认初始值,而是直接拿到获取到的数据,然后render?先给出我的结论,created 和 mounted 中基本无差,两者的渲染次数是一致的。
<script> export default { created(){ this.name = 'hello'; setTimeout(() => { this.name = 'haokur' }, 0) }, mounted(){ // this.name = 'xiao' //setTimeout(() => { // this.name = 'haokur' //}, 0) }, render(h){ console.log('执行渲染',this.name) return h('div',{},this.name) } } </script>
将进行两次,也就是再快的数据返回,也是要进行两次 render 的。因为请求和setTimeout 一样都是异步的,所以它的执行结果是在事件队列中等着的,而 render 是当前执行栈中的同步方法,它是执行在事件队列中的方法之前的。
注释 created,放开mounted ,render 方法则会执行三遍。
但是 created 和 mounted 中直接赋值则是有差别的,因为 render 会发生在 mounted 之前一次。也就是初始化时,created =》render =》 mounted =》(若有更改,再次 render) =》 请求返回 =》 再次 render
所以最佳的处理方式是,同步更改数据的,放 created 中,这样一些初值在第一次渲染就能正确呈现,且比在 mounted 中少执行一遍 render ,异步更改的无所谓。
- is 的使用,在一些特定的结构中使用组件,如 ul 下的 li
// UserItem.js <template> <li>this is useritem</li> </template> // container.js <template> <ul> <li is="user-item"></li> </ul> </template> <script> import UserItem from './UserItem.js' export default { components:{ 'user-item':UserItem } } </script>
双向数据绑定的说法再圆一下
三大框架对比,有条理点理一下
vue 的 functional 属性
Proxy
以上所述就是小编给大家介绍的《vue使用总结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JS 压缩/解压工具
在线压缩/解压 JS 代码
HTML 编码/解码
HTML 编码/解码