让你明明白白学知识,有代码,有讲解,抄的走,学的会!
一、vue 中使用jsx 写组件
直接上代码
<script>
export default {
name: 'breadcrum',
props: {
breadcrumbList: {
type: Array,
defalut: () => []
}
},
data() {
return {
row: {
id: '',
text: ''
}
}
},
render () {
console.log(this.breadcrumbList)
return (
<div>
{
this.breadcrumbList.map((p, index) => {
if (index === this.breadcrumbList.length - 1) {
return <span>{p.text}</span>
} else {
return <span onclick={() => this.getCurrentIndex(p)}>{p.text}></span>
}
})
}
<p class='current'>当前点击了--> {this.row.text}</p>
</div>
)
},
methods: {
getCurrentIndex (item) {
console.log(item)
this.row = item
}
}
}
</script>
<style lang='scss' scoped>
.current {
margin: 10px 0;
margin-left: 30px;
color: red;
}
</style>
在父组件中使用上面的 breadcrumb 组件, 在使用 jxs编写的组件 传参和注册组件的方式,没有任何区别
<template>
<div>
<breadcrumb :breadcrumbList='breadcrumbList'></breadcrumb>
</div>
</template>
import breadcrumb from './components/breadcrumb'
export default {
components: {
breadcrumb
},
data() {
return {
breadcrumbList: [
{id: 1, text: '一级标签'},
{id: 2, text: '二级标签'},
{id: 3, text: '三级标签'}
]
}
}
}
效果图
上面能这样写,是因为有 babel 插件 将我们的 vue中的 jsx 转换成 render 渲染函数
注意事项
在 vue中使用 jsx 语法,如果熟悉 react语法的人,去看这个,基本还OK,vue中的 jxs 比 react多了的就是
- 上下文this的绑定
- react中写 class是 className ,vue中绑定class 还是class
- jxs 中是没有 for 这个东西的,如果要遍历 列表,使用 map
- 事件绑定,就行内事件的绑定方式 onclick, onchange, onmounsedown, onmouseleave 等
- 使用jsx 再没有那些简单的语法糖方法, 比如 v-model.lazy @keyup.enter等等,要实现,就自己用原生写
二、使用 render 方法写组件
现在我们使用vue 本身提供的 render 方法,写一个简单的内容,在不掺杂成熟的组件库的情况下,看看过程有多痛苦
原生HTML 结构, 非vue 我想表达的HTML结构如下
<div class='bg-red'>
<button>倒置</button>
<button>添加</button>
<div>
<div>1</div>
<div>2</div>
<div>3</div>
.......
</div>
</div>
好,开始 render 函数,硬刚
renderCom.vue 组件
<script>
export default {
name: 'renderComponent',
data () {
return {
arr: [1, 2, 3, 4, 5]
}
},
render (h) {
let arr = this.arr
return h('div', {
class: 'bg-red',
title: '我是一个属性',
style: {
border: "1px solid red"
},
// 增加自定义属性
attrs: {
age: 12
}
}, [
// 数组增加多个子节点
h('button', {
// 绑定事件
on: {
// 箭头函数是为了 获取到 data中的内容,否则上面要定义一个 self = this
click: () => {
// 获取data中的数据,并倒置
this.arr = this.arr.reverse()
}
}
}, '倒置'),
h('button', {
on: {
click: () => {
this.arr.push(this.arr.length + 1)
}
}
}, '添加')
, h('div', {
style: {
// 复合样式,大写
marginTop: '50px'
}
// 没有for循环,循环使用 map 然后 返回 虚拟节点 h('div')
}, arr.map(p => h('div', {
style: {
height: '32px',
borderBottom: '1px dashed #fefefe',
// 还有这种,引号,横线写法,类 css
'padding-left': '40px'
}
}, p)))])
}
}
</script>
<style scoped>
.bg-red {
background: red;
}
</style>
render函数输出组件-效果图
乍一看,我嘞个去,这是啥, 太恶心了吧, 代码行数 55行
废话不多说,直接进入重点
注意事项
- 事件的绑定, on ,render写法 没有模板的语法糖了, v-model.lazy 之类的,想要类似效果,纯原生js,自己刚
- 样式绑定和 纯原生js的是差不多的
- 事件绑定,需要注意使用 data中的内容,请使用 箭头函数, 否则 this指向不对;
- 子元素(子组件), 使用 [] 继续编写 render函数,仍旧返回 虚拟DOM
- 遍历节点, template写法有语法糖 v-for , render写法, map 自己使用 h() 仍旧返回虚拟DOM
- 自定义属性,写在 attrs中, jquery时代,特别喜欢挂载自定义属性,进行传参, 那在render中,就都放在 attrs中
反正恶心的写法你也见到了,还不去写 template写法,写业务,template写法,在可维护上,代码的简洁程度高了一大截,这是毋庸置疑的, 但是有人就是说,我就要 render或者 jxs 的灵活, 用法没有绝对的好坏, “好刀用在钢刃上”, 你说是吧
三、番外篇
使用 render 函数返回组件的内容,就没有 vue是不会再从 template 中或者指定的el中提取模板了
这里我们从 Vue 的生命周期图可以知道,如果有template 就会将template中的内容编译到 render中, 所以,render 函数的目的就是 返回虚拟DOM
render --》 template --》 el
<template>
<div>一些内容</div>
</template>
export default {
el: '这里可以指定一个模版',
render() {
return (
<div>以这个内容为主要</div>
)
}
}
上面这个,在UI层展示的内容,只有 render 返回的, template中的直接被丢弃