Vue 中构建虚拟DOM可以直接使用渲染函数构建虚拟Dom,正常情况下用render函数的参数createElement方法构建虚拟Dom的语法比较繁琐,更方便的是用更接近于模板的JSX语法。
Vue实例与组件入门
我的vue脚手架是vue cli4,如果在新建项目时安装了babel,则自动安装了编译JSX需要的babel插件
babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
这种情况下,render()支持JSX语法。
Vue中定义模板的几种方法
JSX(Javascript XML)是React发明的一种JavaScript的语法扩展,允许 HTML 与 JavaScript 的混写;JSX本身也是一个表达式,在编译后,JSX表达式会变成普通的JavaScript对象。
JSX语法不能被浏览器识别,需要Babel 转义成普通的JavaScript对象。
1、在JSX中可以在大括号{}里任意使用JavaScript表达式
2、必须包含一个根节点
3、标签必须正确嵌套,标签必须关闭,允许单标签,属性名会自动转为小写
4、注释的写法
注释需要包含在{}里
{/* **** */}
单文件组件的模板
<template>
<div>
<p>Hello {{message}}p>
div>
template>
<script>
export default {
data () {
return { message: 'Vue' }
}
}
script>
render函数使用JSX构建虚拟Dom
export default {
data () {
return { message: 'Hello Vue!' }
},
render: function (h) {
return (
<div>
<p>Hello {this.message}</p>
</div>
)
}
}
JSX不支持模板语法中的插值表达式,在JSX直接用{}包裹js表达式
只需要将组件导入,无需在components选项中声明
import MyHeader from './MyHeader'
export default {
render(){
return (
<MyHeader>用户登录</MyHeader>
)
}
}
跟普通的 HTML一样,动态属性要用{}包裹
<div>
{this.message}p>
div>
常见的指令
render(){
return (
<div>
{/* v-model */}
<input vModel={this.newTodoText} />
{/* v-model 以及修饰符 */}
<input vModel_trim={this.newTodoText} />
{/* v-on 监听事件 */}
<input vOn:click={this.newTodoText} />
{/* v-on 监听事件以及修饰符 */}
<input vOn:click_stop_prevent={this.newTodoText} />
{/* v-html */}
<p domPropsInnerHTML={html} />
</div>
)
}
以下方式都可以,在使用不同的babel转义时,写法可能不同
<button vOn:click={this.handleClick}>确定button>
<button onClick={this.handleClick}>确定button>
<button on-click={this.handleClick}>确定button>
子组件
render () {
return (
<div class="header">
{this.$slots.title}
{this.$slots.default}
</div>
)
}
相当于模板
<template>
<div class="header">
<slot name="title">slot>
<slot>slot>
div>
template>
父组件
render () {
return (
<MyHeader>
<h1 slot="title">具名插槽</h1>
<p>默认插槽的内容</p>
</MyHeader>
)
}
同模板语法一致
render () {
return (
<ul>
<li>1.a</li>
<li>2.b</li>
<li>3.c</li>
</ul>
)
}
上面的代码通过循环语句实现:
render () {
const todos = ['a', 'b', 'c']
return (
<ul>
{
todos.map((item,index)=> {
return <li>{index}.{item}</li>
})
}
</ul>
)
}
render () {
const condition = true
return (
<div>
{
condition
? <span>1</span>
: <span>0</span>
}
</div>
)
}
render () {
const condition = true
let content = ''
if (condition) {
content = <span>1</span>
} else {
content = <span>0</span>
}
return (
<div>
{content}
</div>
)
}
官方文档
vue中的函数式组件也称为无状态组件,只有props选项,典型场景是如果一个组件没有复杂的交互,只用来展示DOM,用函数式组件则即快速又方便。
假设设计一个显示文章内容的函数式组件,其中有两个插槽一个是作者结束,一个是版权信息
<about-article id="1" class="article" style="font-size: 16px" className="article-article" title="标题" content="内容" @read="handleRead">
<div>作者介绍div>
<p slot="copyright">版权所有p>
about-article>
export default {
functional:true,
render(h,context){
console.log(context)
return (
<div onClick={context.listeners.read}>
{context.children[0]}
<h1>{context.props.title}</h1>
<div>{context.props.content}</div>
{context.slots().copyright}
</div>
)
}
}
在 2.3.0 及以上的版本中,如果不配置 props 选项,所有组件上的 attribute 都会被自动隐式解析为 prop。
如配置props选项,props将只包含配置的属性
props: ['title', 'content']
injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。
子组件
render (h, context) {
console.log(context)
return (
<div onClick={context.listeners.read}>
{context.children[0]}
<h1>{context.props.title}h1>
<div>{context.props.content}div>
{context.slots().copyright}
div>
)
}
单文件组件可以使用基于模板的函数式组件
<template functional>
template>