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是什么

JSX(Javascript XML)是React发明的一种JavaScript的语法扩展,允许 HTML 与 JavaScript 的混写;JSX本身也是一个表达式,在编译后,JSX表达式会变成普通的JavaScript对象。

JSX语法不能被浏览器识别,需要Babel 转义成普通的JavaScript对象。

JSX语法规则

1、在JSX中可以在大括号{}里任意使用JavaScript表达式
2、必须包含一个根节点
3、标签必须正确嵌套,标签必须关闭,允许单标签,属性名会自动转为小写
4、注释的写法
注释需要包含在{}里

{/* **** */}

使用JSX构建虚拟Dom

单文件组件的模板

<template>
  <div>
    <p>Hello {{message}}</p>
  </div>
</template>

<script>
  export default {
    data () {
        return { message: 'Vue' }
      }
  }
</script>

render函数使用JSX构建虚拟Dom

  • render函数中this指向当前实例
  • render函数的参数createElement,JSX 中要用简写h。
  • return的内容就是虚拟dom.使用的语法是JSX语法,它看起来和上例中的模板很像,语法规则中的最重要的一点就是要在大括号{}里使用JavaScript表达式
export default {
  data () {
    return { message: 'Hello Vue!' }
  },
  render: function (h) {
    return (
      <div>
        <p>Hello {this.message}</p>
      </div>
    )
  }
}

插值表达式

JSX不支持模板语法中的插值表达式,在JSX直接用{}包裹js表达式

JSX中引用组件

只需要将组件导入,无需在components选项中声明

import MyHeader from './MyHeader'
export default {
  render(){
    return (
      <MyHeader>用户登录</MyHeader>
    )
  }
}

属性的写法

跟普通的 HTML一样,动态属性要用{}包裹

<div>
  <p id="a" class={'b'}>{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>
  )
}
  • if - else
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>
  • 子组件(函数式组件)
    函数式组件内部没有响应式数据,没有this,但在其render函数的参数中多了一个参数context,提供了很多有用的信息
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>
    )
  }
}

在这里插入图片描述

context参数

props 提供所有 prop 的对象

在 2.3.0 及以上的版本中,如果不配置 props 选项,所有组件上的 attribute 都会被自动隐式解析为 prop。
在这里插入图片描述
如配置props选项,props将只包含配置的属性

props: ['title', 'content']

在这里插入图片描述

data 传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
  • 不配置 props 选项
    在这里插入图片描述
  • 配置props 选项
    在这里插入图片描述
children VNode 子节点的数组

在这里插入图片描述

slots 一个函数,返回包含所有插槽的对象
scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。

在这里插入图片描述

parent 对父组件的引用
listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。

在这里插入图片描述

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>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐