Vue.js 你不知道的冷(qi)门(ji)知(yin)识(qiao)
栏目: JavaScript · 发布时间: 6年前
内容简介:面试官:MVVM 和 MVC 的区别是什么?自己先想一分钟。关于上面的面试题的具体解释,请移步这里,本文不在累述。正文开始,下面列举的一些奇技淫巧有的或许你用过,有的或许你没用过。不管有的没的,希望你看完之后有所收获吧。文笔和知识有限,不对的地方,请留言斧正!
面试官:MVVM 和 MVC 的区别是什么?
自己先想一分钟。
关于上面的面试题的具体解释,请移步这里,本文不在累述。正文开始,下面列举的一些奇技淫巧有的或许你用过,有的或许你没用过。不管有的没的,希望你看完之后有所收获吧。文笔和知识有限,不对的地方,请留言斧正!
给 props 属性设置多个类型
这个技巧在开发组件的时候用的较多,为了更大的容错性考虑。比如一个 <my-button>
上暴露了一个 width
属性:
// my-button.vue export default { props: { width: [String, Number], default: '100px' } } 复制代码
我们既可以传 100px
,也可以传 100
。
<!-- my-button.vue --> <template> <button :style="computedWidth">width: {{ computedWidth }}</button> </template> <script> export default { props: { width: [String, Number], default: '100px' }, computed: { computedWidth () { let o = {} if (typeof this.width === 'string') o.width = this.width if (typeof this.width === 'number') o.width = this.width + 'px' return o } } } </script> 复制代码
使用:
<!-- 在其他组件中使用 --> <template> <my-button width="100px"></my-button> <!-- or --> <my-button width="100"></my-button> </template> 复制代码
data初始化
因为 props
要比 data
先完成初始化,所以我们可以利用这一点给 data
初始化一些数据进去,看代码:
export default { data () { return { buttonSize: this.size } }, props: { size: String } } 复制代码
除了以上,子组件的 data
函数也可以有参数,且该参数是当前实例对象。所有我们可以利用这一点做一些自己的判断。如,改写上面的代码:
export default { data (vm) { return { buttonSize: vm.size } }, props: { size: String } } 复制代码
template
我们在做 v-if
判断的时候,可以把判断条件放在 template
组件上,最终的渲染结果将不包含 <template>
元素。
<template> <div class="box"> <template v-if="isVal"> <h2>...</h2> </template> <template v-else> <h2>...</h2> </template> </div> </template> 复制代码
v-for
也同样适用。
Lifecycle hook
生命周期钩子可以是一个数组类型,且数组中的函数会依次执行。
export default { ... created: [ function one () { console.log(1) }, function two () { console.log(2) } ] ... } 复制代码
没什么用,知道就行了。事实上生命周期钩子还可以作用于 DOM 元素上,利用这一点,我们可以用父组件中的方法来初始化子组件的生命周期钩子:
<!-- Child.vue --> <template> <h3>I'm child!</h3> </template> <!-- Parent.vue --> <template> <child @hook:created="handleChildCreated"></child> </template> <script> import Child from './child.vue' export default { components: [ Child ], methods: { handleChildCreated () { console.log('handle child created...') } } } </script> 复制代码
其他钩子雷同,不再赘述。
v-for 和 v-if 一起使用
由于 v-for
比 v-if
渲染优先级更高,所以有时候可以一起使用。下面两种常见的情况下会倾向于把 v-for
和 v-if
放在同一个标签上使用:
- 筛选一些不想显示的条目
- 为了避免渲染本应该被隐藏的列表
举个栗子:
<template> <ul class="items"> <!-- 只有激活的用户才可以显示 --> <li v-for="(user, index) in users" v-if="user.isActive" :key="user.id">{{ user.name }}</li> </template> 复制代码
关于以上两点不明白的地方可以参见Vue 风格指南。
混合
如果好多组件都共用到一些像 props
、 data
、 methods
等,可以单独抽出来放到 mixins
混合器中。
// paging-mixin.vue export default { props: { pageSize: 1, pageLength: 10, currentPage: 1 total: 20 }, methods: { /** * 上一页 */ prevPage (page) { ... }, /** * 下一页 */ nextPage (page) { ... } /** * 跳转到当前页 */ currentPage (page) { ... } } } 复制代码
比如在用户管理列表使用:
<!-- Users.vue --> <template> <div class="user-model"> <my-table :data="users"></my-table> <my-paging :page-length="pageLength" :page-size="pageSize" :current-page="currentPage" :total="total"> </my-paging> </div> </template> <script> import PagingMixin from '../mixins/paging-mixin.vue' export default { mixins: [PagingMixin], data () { return { users: [], pageLength: 10, pageSize: 1, currentPage: 1, total: 20 } } } </script> 复制代码
不用每个页面都写一遍 props
和 methods
了。
render 函数
下面是一段简单的 template 模板代码:
<template> <div class="box"> <h2>title</h2> this is content </div> </template> 复制代码
我们用渲染函数来重写上面的代码:
export default { render (h) { let _c = h return _c('div', { class: 'box'}, [_c('h2', {}, 'title'), 'this is content']) } } 复制代码
事实上,Vue 会把模板(template)编译成渲染函数(render),你可以通过一个在线 工具 实时查看编译结果。上面的 template 模板会被编译成如下渲染函数:
let render = function () { return _c('div', {staticClass:"box"}, [_c('h2', [_v("title")]), _v("this is content")]) } 复制代码
是不是很像? 正如官方说的, 渲染函数比 template 更接近编译器 。如果用一个流程图来解释的话,大概是这个样子:
template ↓ 预编译工具(vue-loader + vue-template-compile) ↓ render ↓ resolve vnode 复制代码
具体参见Vue声明周期图示。
渲染函数用处:
- 开发组件库,Element 源码用的都是 render
- 封装一些高阶组件。组件里面嵌套组件就是高阶组件,前提是要满足组件三要素:
props
、event
、slot
- 用于处理一些复杂的逻辑判断。如果我们一个组件里面有很多的
v-if
判断的话,用模板就显得不合适了,这个时候可以用渲染函数来轻松处理
errorCaptured
捕获一个来自子孙组件的错误时被调用。有时候当我们想收集错误日志,却不想把错误暴露到浏览器控制台的时候很有用。下面是个例子:
Child.vue
<template> <!-- 省略一些无关代码 --> </template> <script> export default { mounted () { // 故意把 console 写错 consol.log('这里会报错!') } } </script> 复制代码
Parent.vue
<template> <!-- 省略一些无关代码 --> </template> <script> import Child from './Child.vue' export default { components: [ Child ], /** * 收到三个参数: * 错误对象、发生错误的组件实例 * 以及一个包含错误来源信息的字符串。 * 此钩子可以返回 false 以阻止该错误继续向上传播。 */ errorCaptured (err, vm, info) { console.log(err) // -> ReferenceError: consle is not defined ... console.log(vm) // -> {_uid: 1, _isVue: true, $options: {…}, _renderProxy: o, _self: o,…} console.log(info) // -> `mounted hook` // 告诉我们这个错误是在 vm 组件中的 mounted 钩子中发生的 // 阻止该错误继续向上传播 return false } } </script> 复制代码
关于 errorCaptured 更多说明,请移步官网-> 。
v-once
通过 v-once
创建低开销的静态组件。渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,你可以在根元素上添加 v-once
特性以确保这些内容只计算一次然后缓存起来,就像这样:
<template> <div class="box" v-once> <h2> 用户协议 </h2> ... a lot of static content ... </div> </template> 复制代码
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。关于 v-once
更多介绍,请移步官网->。
slot-scope
作用域插槽。 vue@2.5.0
版本以前叫 scope
,之后的版本用 slot-scope
将其代替。除了 scope 只可以用于 <template>
元素,其它和 slot-scope
都相同。
用过 Element 组件的同学都知道,当我们在使用 el-table 的时候会看到如下代码:
Element@1.4.x 的版本:
<el-table-column label="操作"> <template scope="scope"> <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button> </template> </el-table-column> 复制代码
但在 2.0 之后的版本替换成了 slot-scope
。
Element@2.0.11:
<el-table-column label="操作"> <template slot-scope="scope"> <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button> </template> </el-table-column> 复制代码
说白了, slot-scope
相当于函数的回调,我把结果给你,你想怎么处理就怎么处理,一切随你:
function getUserById (url, data, callback) { $.ajax({ url, data, success: function (result) { callback(result) } }) } // 使用 getUserById('/users', { id: 1 }, function (response) { // 拿到数据并开始处理自己的页面逻辑 }) 复制代码
下面我们来简单模拟下 <el-table>
组件内部是怎么使用 slot-scope
的,看代码:
// 定义模板 let template = ` <ul class="table"> <li v-for="(item, index) in data" :key="index"> <!-- 我希望数据由调用者自己处理 --> <!-- 'row' 相当于变量名,随便起名 --> <slot :row="item">ddd</slot> </li> </ul> ` // 声明 `el-table` 组件 Vue.component('el-table', { template, props: { data: Array, default: [] } }) // 根组件 new Vue({ el: '#app', data: { userData: [ {id: 1, name: '张三', isActived: false}, {id: 2, name: '李四', isActived: false}, {id: 1, name: '王五', isActived: true}, {id: 1, name: '赵六', isActived: false}, ] } }) 复制代码
组件使用:
<div id="app"> <el-table :data="userData"> <!-- 使用的时候可以用 template --> <!-- `scope` 只是个形参,随便起名 --> <template slot-scope="scope"> <template v-if="scope.row.isActived"> <span class="red">{{ scope.row.name }}</span> </template> <template v-else> {{ scope.row.name }} </template> </template> </el-table> </div> 复制代码
CSS:
.red { color: red } 复制代码
我们完全可以在 <li>
中进行逻辑判断,为什么还要放到外面进行处理呢? 因为有时候我们用的不是自己开发的组件,比如上面的 <el-table>
,所以就有必要这么做了。最后,你可以狠狠的戳这里查看效果!
结尾!
啰嗦了这么多,希望看到的同学或多或少有点收获吧。不对的地方还请留言指正,不胜感激。俗话说, 三人行则必有我师! 希望更多志同道合的小伙伴能聚在一起交流技术!下面的群快满了,可以加我 Q1769617251 。备注 vue 即可。
以上所述就是小编给大家介绍的《Vue.js 你不知道的冷(qi)门(ji)知(yin)识(qiao)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 谈谈大家想知道的、不知道的SDN
- 你知道和你不知道的冒泡排序
- JS数组中那些你知道或不知道的
- 掌握Python列表理解需要知道的9件事,你知道吗?
- 你所知道或不知道的CSS content属性
- 前端程序员不知道的14个JavaScript调试技巧,你知道几个?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。