Vue 开发必须知道的36个技巧(小结)(3)

// 父组件 <todo-list> <template v-slot:todo="slotProps" > {{slotProps.user.firstName}} </template> </todo-list> //slotProps 可以随意命名 //slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user" // 子组件 <slot :user="user" :test="test"> {{ user.lastName }} </slot> data() { return { user:{ lastName:"Zhang", firstName:"yue" }, test:[1,2,3,4] } }, // {{ user.lastName }}是默认数据 v-slot:todo 当父页面没有(="slotProps")

3.11 EventBus

1.就是声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上;
2.类似于 Vuex。但这种方式只适用于极小的项目
3.原理就是利用$on和$emit 并实例化一个全局 vue 实现数据共享

// 在 main.js Vue.prototype.$eventBus=new Vue() // 传值组件 this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值') // 接收组件 this.$eventBus.$on("eventTarget",v=>{ console.log('eventTarget',v);//这是eventTarget传过来的值 })

4.可以实现平级,嵌套组件传值,但是对应的事件名eventTarget必须是全局唯一的

3.12 broadcast和dispatch

vue 1.x 有这两个方法,事件广播和派发,但是 vue 2.x 删除了

下面是对两个方法进行的封装

function broadcast(componentName, eventName, params) { this.$children.forEach(child => { var name = child.$options.componentName; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { broadcast.apply(child, [componentName, eventName].concat(params)); } }); } export default { methods: { dispatch(componentName, eventName, params) { var parent = this.$parent; var name = parent.$options.componentName; while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.componentName; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, broadcast(componentName, eventName, params) { broadcast.call(this, componentName, eventName, params); } } }

3.13 路由传参

1.方案一

// 路由定义 { path: '/describe/:id', name: 'Describe', component: Describe } // 页面传参 this.$router.push({ path: `/describe/${id}`, }) // 页面获取 this.$route.params.id

2.方案二

// 路由定义 { path: '/describe', name: 'Describe', omponent: Describe } // 页面传参 this.$router.push({ name: 'Describe', params: { id: id } }) // 页面获取 this.$route.params.id

3.方案三

// 路由定义 { path: '/describe', name: 'Describe', component: Describe } // 页面传参 this.$router.push({ path: '/describe', query: { id: id `} ) // 页面获取 this.$route.query.id

4.三种方案对比
方案二后面参数页面刷新会丢失
方案一参数拼接在后面,丑,而且暴露了信息
方案三不会在后面拼接参数,刷新参数也不会丢失

3.14 Vue.observable

2.6.0 新增
用法:让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象;

返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新;
也可以作为最小化的跨组件状态存储器,用于简单的场景。

通讯原理实质上是利用Vue.observable实现一个简易的 vuex

// 文件路径 - /store/store.js import Vue from 'vue' export const store = Vue.observable({ count: 0 }) export const mutations = { setCount (count) { store.count = count } } //使用 <template> <div> <label for="bookNum">数 量</label> <button @click="setCount(count+1)">+</button> <span>{{count}}</span> <button @click="setCount(count-1)">-</button> </div> </template> <script> import { store, mutations } from '../store/store' // Vue2.6新增API Observable export default { name: 'Add', computed: { count () { return store.count } }, methods: { setCount: mutations.setCount } } </script>

4.render 函数

1.场景:有些代码在 template 里面写会重复很多,所以这个时候 render 函数就有作用啦

// 根据 props 生成标签 // 初级 <template> <div> <div v-if="level === 1"> <slot></slot> </div> <p v-else-if="level === 2"> <slot></slot> </p> <h1 v-else-if="level === 3"> <slot></slot> </h1> <h2 v-else-if="level === 4"> <slot></slot> </h2> <strong v-else-if="level === 5"> <slot></slot> </stong> <textarea v-else-if="level === 6"> <slot></slot> </textarea> </div> </template> // 优化版,利用 render 函数减小了代码重复率 <template> <div> <child :level="level">Hello world!</child> </div> </template> <script type='text/javascript'> import Vue from 'vue' Vue.component('child', { render(h) { const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level] return h(tag, this.$slots.default) }, props: { level: { type: Number, required: true } } }) export default { name: 'hehe', data() { return { level: 3 } } } </script>

2.render 和 template 的对比

前者适合复杂逻辑,后者适合逻辑简单;
后者属于声明是渲染,前者属于自定Render函数;
前者的性能较高,后者性能较低。

5.异步组件

场景:项目过大就会导致加载缓慢,所以异步组件实现按需加载就是必须要做的事啦
1.异步注册组件
3种方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/a095a9d4ae03baec37d1a088cb09a2e5.html