1.1认识h函数(hyperscript工具 基于JavaScript编写模板的工具)
Vue推荐在绝大多数情况下使用模板来创建你的HTML,然后一些特殊的场景,需要JavaSript的完全编程能力,
可以使用渲染函数,它比模板更接近编译器;
VNode和VDOM的生成:
Vue在生成真实的DOM之前,会将我们的节点转换成VNode,而Vnode组合在一起形成一棵树结构,就是虚拟DOM(VDOM)
编写template中的html最终也是使用渲染函数生成对应的VNode;
可以利用JavaScript的编程能力,我们可以自己来编写createdVnode函数,生成对应的VNode;
h函数:
创建VNode的一个函数;
更准备命名的是createdVnode函数,为了简便在Vue中简化为h函数;
注意事项:
如果没有props,那么通常可以将children作为第二个参数传入;
如果会产生歧义,可以将null作为第二个参数传入,将children作为第三个参数传入;
1.2.h函数在render中的基本用法
// 基本用法
<script>
import { h } from 'vue';
export default {
render () {
return h('h2',{ class: 'title' }, 'Hello Render')
}
}
</script>
1.3.setup函数中返回VNode
<script>
import { ref, h } from 'vue';
export default {
setup(){ // setup可以返回render函数,可以替代掉render函数
const counter = ref(100);
return () => {
return h('div',{ class: 'app' }, [
h('h2',null, `当前计数:${ counter.value }`),
h('button',{ onClick: () => counter.value++ }, '+1'),
h('button',{ onclick: () => counter.value-- }, '-1')
])
}
},
// render () { // 可以使用this去拿数据,因为render函数内部是绑定了this
// return h('div',{ class: 'app' }, [
// h('h2',null, `当前计数:${this.counter}`),
// h('button',{ onClick: () => this.counter++ }, '+1'),
// h('button',{ onclick: () => this.counter-- }, '-1')
// ])
// }
}
</script>
1.4.render函数中使用插槽
<script>
// 父组件
import { ref, h } from 'vue';
import HelloWorld from './HelloWorld.vue'
export default {
// setup中的return对象怎么放进render函数中?
// 不是放进去,对this做了一个代理, 例如:取this.counter的时候,proxy(, setupData里面去找这个数据,然后依次是data/ctx/props)
render(){ // setup可以返回render函数,可以替代掉render函数
return ('div', null, [
h(HelloWorld, null, {
default: props => h('h2', null,`我是App的插槽:${props.name}`)
})
])
},
}
</script>
<script>
// 子组件
import { h } from 'vue'
export default {
render () {
return h('div', null, [
h('h2', null, 'hello world'),
this.$slots.default ? this.$slots.default({ name: 'coderwhy' }) : h('h2', null, '我是helloworld默认的插槽')
])
}
}
</script>
2.1 JSX基本用法
JSX是一种JavaScript的语法扩展,首先运用于React中,其格式比较像是模版语言,但事实上完全是在JavaScript内部实现的。
jsx的babel配置
在项目中使用jsx,那么我们需要添加对jsx的支持:
jsx通常通过babel来进行转换(React编写的jsx就是通过babel转换的)
对于Vue,只需要在babel中配置对应的插件即可;
babel(工具)
jsx -> render h()
<script lang="jsx">
import { ref } from 'vue'
import HelloWorld from './HelloWorld.vue'
// 父组件
export default {
setup () {
const counter = ref(0)
return {
counter,
}
},
render() {
const increment = () => this.counter++
const decrement = () => this.counter--
return (
// 下面jsx的html会通过babel转化成h函数,
<div>
<h2>当前计数:{ this.counter }</h2>
<button onClick={ increment }>+1</button>
<button onClick={ decrement }>-1</button>
<HelloWorld >
{ {default: props => <button onClick={ increment }>我是按钮</button> } }
</HelloWorld>
</div>
)
}
}
</script>
<script lang="jsx">
// 子组件
export default {
render () {
return (
<div>
<h2>Hello World</h2>
{ this.$slots.default? this.$slots.default() : '哈哈哈哈' }
</div>
)
}
}
</script>