使用vue的渲染函数时给我的感觉就是想在使用原生的js创建虚拟dom类似,很繁琐,
而jsx就类似于原生js中的innerHTML中书写HTML代码
在Vue中使用JSX语法。可以让我们回到更接近模板的语法上。
注意
在jsx中 <>
内输入的是HTML代码 {}
内输入的js代码
插值
<div>{ this.value }</div>
指令
在JSX中,一些指令并不存在,所以我们可以换一种方式来处理。
v-text
<div domPropsTextContent="<p>i am a p</p>"></div>
v-html
<div domPropsInnerHTML="<p>i am a p</p>"></div
v-show
js-x支持v-show指令
<div v-show={this.show}></div>
v-if
<!-- v-if -->
<script>
export default {
data(){
return {
bool:true,
}
},
methods:{
vIf(num){
if(num == 1){
return <h1>1</h1>
}else if(num == 2){
return <h1>2</h1>
}else{
return <h1>3</h1>
}
},
},
render(){
return (
<div>
v-if 第一种方式
{true && <h1>if</h1>}
第二种方式
{ !this.bool ? <h1>false</h1>:<h1>true</h1> }
第三种方式
{this.vIf(3)}
</div>
)
}
}
</script>
v-for
v-for 与 key
{this.arr.map(ele => <h1 key={ele}>v-for:{ele}</h1>)}
v-on
<script>
import baseDemo from './baseDemo'
export default {
methods:{
handleClick(str,e){
console.log(123)
console.log(str,e.target)
}
},
components:{
baseDemo,
},
render(){
return (
<div>
事件监听
<h1 on-click={this.handleClick}>click</h1>
也可使用
<h1 onClick={this.handleClick}>click</h1>
原生事件监听
<h1>
<base-demo nativeOnClick={this.handleClick}/>
</h1>
事件监听+传递参数
<h1 on-click={e => this.handleClick('我是参数',e)}>click传递参数</h1>
</div>
)
}
}
</script>
v-bind
直接书写特姓名
<input value={this.value}/>
内联样式
<div class="a b c d " style="background:blue; width:100px; height:100px;">123456</div>
在JSX中可以直接使用class="xx"来指定样式类,内联样式可以直接写成style="xxx"
<div class='a'>单个class</div>
class
<div class={{a:true,b:false,c:true}}>class</div>
style
<div style={{ color:'red',fontSize:'20px'}}>style</div>
v-model
有相应的插件 支持 v-model,所以可以直接使用:
<input type="text" v-model={this.value} />
Ref
<script>
export default {
data(){
return {
arr:[1,2,3,4,5,6,7],
}
},
render(){
return (
<div>
<p>Ref--访问子组件实例或子元素</p>
<input ref="input" value="123456789"/>
当为v-for时ref特性应该包括所有循环生成的元素,而不是只有最后一个
<ul>
{this.arr.map(ele => <li ref="li" key={ele} refInFor={true}>{ele}</li>)}
</ul>
</div>
)
},
mounted(){
console.log(this.$refs)
console.log(this.$refs.input.value)
console.log(this.$refs.li[1].innerText)
}
}
</script>
自定义指令
两种方式
- 写在行间上
- 写成对象
写在行间上
<script>
// 写在行间上
export default {
data(){
return {
value:'123456'
}
},
directives:{
'slice':{
bind (el, binding, vnode) {
const vm = vnode.context;
let { value, expression, arg, modifiers } = binding.value;
console.log(binding,'directive-行间书写')
if(modifiers.number) {
value = value.replace(/[^0-9]/g, '');
}
el.value = value.slice(0, arg);
vm[expression] = value.slice(0, arg);
el.oninput = function (e) {
let inputVal = el.value;
if(modifiers.number) {
inputVal = inputVal.replace(/[^0-9]/g, '');
}
el.value = inputVal.slice(0, arg);
vm[expression] = inputVal.slice(0, arg);
}
},
update (el, binding, vnode) {
const vm = vnode.context;
let { value, arg, expression, modifiers } = binding.value;
if(modifiers.number) {
value = value.replace(/[^0-9]/g, '');
}
el.value = value.slice(0, arg);
vm[expression] = value.slice(0, arg);
},
}
},
// 写在行间上
render(){
return (
<div>
写在行间上
<input v-slice={{value:this.value,expression:'value',arg:5,modifiers: {number: true},}}/>
{this.value}
</div>
)
}
}
</script>
使用对象的方式
<script>
// 自定义对象,使用对象的方式
export default {
data(){
return {
value:'123456'
}
},
directives:{
'slice':{
bind (el, binding, vnode) {
const vm = vnode.context;
let { value, expression, arg, modifiers } = binding; // 写在行间上此处的数据储存位置不一样
console.log(binding,'directive-对象展开')
if(modifiers.number) {
value = value.replace(/[^0-9]/g, '');
}
el.value = value.slice(0, arg);
vm[expression] = value.slice(0, arg);
el.oninput = function (e) {
let inputVal = el.value;
if(modifiers.number) {
inputVal = inputVal.replace(/[^0-9]/g, '');
}
el.value = inputVal.slice(0, arg);
vm[expression] = inputVal.slice(0, arg);
}
},
update (el, binding, vnode) {
const vm = vnode.context;
let { value, arg, expression, modifiers } = binding;
if(modifiers.number) {
value = value.replace(/[^0-9]/g, '');
}
el.value = value.slice(0, arg);
vm[expression] = value.slice(0, arg);
},
}
},
render(){
const directives = [
{
name:'slice',
value:this.value,
expression:'value',
arg:5,
modifiers:{
number:true,
}
}
]
return (
<div>
使用对象展开的方式
<input {...{directives}}/>
{this.value}
</div>
)
}
}
</script>
过滤器
<!-- 正常使用过滤器 -->
<div>{{ msg | capitalize }}</div>
<!-- 在jsx中使用过滤器 -->
<div>{ this.$options.filters['capitalize'](this.msg)}</div>
示例
<script>
// <template>
// <div> {{ msg | capitalize }}</div>
// </template>
export default {
data(){
return{
msg : 'wula'
}
},
filters:{
capitalize(value){
if(value) return "我过滤器"
}
},
render(){
console.log(this,'filter')
console.log(this.$options,'filter')
return (
<div>{this.$options.filters['capitalize'](this.msg)}</div>
)
}
}
</script>
插槽
普通书写方式和具名插槽
子组件书写示例
<script>
export default {
render(){
return (
<div>
<header>
{this.$slots.header}
</header>
123546
<main>
{this.$slots.default}
</main>
</div>
)
}
}
</script>
父组件使用插槽
<script>
import jsxSlot from './components/jsx-slot'
export default {
components:{
jsxSlot,
},
render(){
return(
<div>
普通插槽与具名插槽
<jsx-slot>
<i>我是默认插槽</i>
<strong slot="header">我是头部</strong>
</jsx-slot>
</div>
)
}
}
</script>
作用域插槽
子组件书写示例
<script>
export default {
data(){
return {
msg:"我是作用域插槽的内"
}
},
render(){
return (
<div>
作用域插槽
{this.$scopedSlots.default({
msg:this.msg,
})}
</div>
)
}
}
</script>
父组件示例
<script>
import jsxSlot2 from './components/jsx-slot2'
export default {
components:{
jsxSlot2,
},
render(){
return(
<div>
作用域插槽
<jsx-slot2 {...{scopedSlots:{default:(props) => props.msg}}}>
</jsx-slot2>
</div>
)
}
}
</script>
jsx利用变量名生成一个元素
示例代码
<script>
export default {
render(){
const tag = "h1";
return(
<tag></tag>
)
}
}
</script>
演示案例
父组件代码
<template>
<base-demo :level="level"> 标题 </base-demo>
</template>
<script>
import baseDemo from "./components/baseDemo";
export default {
name: "App",
components: {
baseDemo,
},
data() {
return {
level: "1",
};
}
}
</script>
子组件代码
<script>
export default {
props:{
level:{
type:String,
required:true,
}
},
render(){
const tag = 'h' + this.props.level
return(
<tag>
{this.$slots.default}
</tag>
)
}
}
</script>