使用vue的渲染函数时给我的感觉就是想在使用原生的js创建虚拟dom类似,很繁琐,
而jsx就类似于原生js中的innerHTML中书写HTML代码
在Vue中使用JSX语法。可以让我们回到更接近模板的语法上。

注意

在jsx中 <> 内输入的是HTML代码 {} 内输入的js代码

插值

  1. <div>{ this.value }</div>

指令

在JSX中,一些指令并不存在,所以我们可以换一种方式来处理。

v-text

  1. <div domPropsTextContent="<p>i am a p</p>"></div>

v-html

  1. <div domPropsInnerHTML="<p>i am a p</p>"></div

v-show

js-x支持v-show指令

  1. <div v-show={this.show}></div>

v-if

  1. <!-- v-if -->
  2. <script>
  3. export default {
  4. data(){
  5. return {
  6. bool:true,
  7. }
  8. },
  9. methods:{
  10. vIf(num){
  11. if(num == 1){
  12. return <h1>1</h1>
  13. }else if(num == 2){
  14. return <h1>2</h1>
  15. }else{
  16. return <h1>3</h1>
  17. }
  18. },
  19. },
  20. render(){
  21. return (
  22. <div>
  23. v-if 第一种方式
  24. {true && <h1>if</h1>}
  25. 第二种方式
  26. { !this.bool ? <h1>false</h1>:<h1>true</h1> }
  27. 第三种方式
  28. {this.vIf(3)}
  29. </div>
  30. )
  31. }
  32. }
  33. </script>

v-for

  1. v-for key
  2. {this.arr.map(ele => <h1 key={ele}>v-for:{ele}</h1>)}

v-on

  1. <script>
  2. import baseDemo from './baseDemo'
  3. export default {
  4. methods:{
  5. handleClick(str,e){
  6. console.log(123)
  7. console.log(str,e.target)
  8. }
  9. },
  10. components:{
  11. baseDemo,
  12. },
  13. render(){
  14. return (
  15. <div>
  16. 事件监听
  17. <h1 on-click={this.handleClick}>click</h1>
  18. 也可使用
  19. <h1 onClick={this.handleClick}>click</h1>
  20. 原生事件监听
  21. <h1>
  22. <base-demo nativeOnClick={this.handleClick}/>
  23. </h1>
  24. 事件监听+传递参数
  25. <h1 on-click={e => this.handleClick('我是参数',e)}>click传递参数</h1>
  26. </div>
  27. )
  28. }
  29. }
  30. </script>

v-bind

  1. 直接书写特姓名
  2. <input value={this.value}/>
  3. 内联样式
  4. <div class="a b c d " style="background:blue; width:100px; height:100px;">123456</div>
  5. JSX中可以直接使用class="xx"来指定样式类,内联样式可以直接写成style="xxx"
  6. <div class='a'>单个class</div>
  7. class
  8. <div class={{a:true,b:false,c:true}}>class</div>
  9. style
  10. <div style={{ color:'red',fontSize:'20px'}}>style</div>

v-model

有相应的插件 支持 v-model,所以可以直接使用:

  1. <input type="text" v-model={this.value} />

Ref

  1. <script>
  2. export default {
  3. data(){
  4. return {
  5. arr:[1,2,3,4,5,6,7],
  6. }
  7. },
  8. render(){
  9. return (
  10. <div>
  11. <p>Ref--访问子组件实例或子元素</p>
  12. <input ref="input" value="123456789"/>
  13. 当为v-forref特性应该包括所有循环生成的元素,而不是只有最后一个
  14. <ul>
  15. {this.arr.map(ele => <li ref="li" key={ele} refInFor={true}>{ele}</li>)}
  16. </ul>
  17. </div>
  18. )
  19. },
  20. mounted(){
  21. console.log(this.$refs)
  22. console.log(this.$refs.input.value)
  23. console.log(this.$refs.li[1].innerText)
  24. }
  25. }
  26. </script>

控制台打印效果
image.png

自定义指令

两种方式

  • 写在行间上
  • 写成对象

两种方式我测试时发现他们储存信息的地方稍微不一样

写在行间上

  1. <script>
  2. // 写在行间上
  3. export default {
  4. data(){
  5. return {
  6. value:'123456'
  7. }
  8. },
  9. directives:{
  10. 'slice':{
  11. bind (el, binding, vnode) {
  12. const vm = vnode.context;
  13. let { value, expression, arg, modifiers } = binding.value;
  14. console.log(binding,'directive-行间书写')
  15. if(modifiers.number) {
  16. value = value.replace(/[^0-9]/g, '');
  17. }
  18. el.value = value.slice(0, arg);
  19. vm[expression] = value.slice(0, arg);
  20. el.oninput = function (e) {
  21. let inputVal = el.value;
  22. if(modifiers.number) {
  23. inputVal = inputVal.replace(/[^0-9]/g, '');
  24. }
  25. el.value = inputVal.slice(0, arg);
  26. vm[expression] = inputVal.slice(0, arg);
  27. }
  28. },
  29. update (el, binding, vnode) {
  30. const vm = vnode.context;
  31. let { value, arg, expression, modifiers } = binding.value;
  32. if(modifiers.number) {
  33. value = value.replace(/[^0-9]/g, '');
  34. }
  35. el.value = value.slice(0, arg);
  36. vm[expression] = value.slice(0, arg);
  37. },
  38. }
  39. },
  40. // 写在行间上
  41. render(){
  42. return (
  43. <div>
  44. 写在行间上
  45. <input v-slice={{value:this.value,expression:'value',arg:5,modifiers: {number: true},}}/>
  46. {this.value}
  47. </div>
  48. )
  49. }
  50. }
  51. </script>

使用对象的方式

  1. <script>
  2. // 自定义对象,使用对象的方式
  3. export default {
  4. data(){
  5. return {
  6. value:'123456'
  7. }
  8. },
  9. directives:{
  10. 'slice':{
  11. bind (el, binding, vnode) {
  12. const vm = vnode.context;
  13. let { value, expression, arg, modifiers } = binding; // 写在行间上此处的数据储存位置不一样
  14. console.log(binding,'directive-对象展开')
  15. if(modifiers.number) {
  16. value = value.replace(/[^0-9]/g, '');
  17. }
  18. el.value = value.slice(0, arg);
  19. vm[expression] = value.slice(0, arg);
  20. el.oninput = function (e) {
  21. let inputVal = el.value;
  22. if(modifiers.number) {
  23. inputVal = inputVal.replace(/[^0-9]/g, '');
  24. }
  25. el.value = inputVal.slice(0, arg);
  26. vm[expression] = inputVal.slice(0, arg);
  27. }
  28. },
  29. update (el, binding, vnode) {
  30. const vm = vnode.context;
  31. let { value, arg, expression, modifiers } = binding;
  32. if(modifiers.number) {
  33. value = value.replace(/[^0-9]/g, '');
  34. }
  35. el.value = value.slice(0, arg);
  36. vm[expression] = value.slice(0, arg);
  37. },
  38. }
  39. },
  40. render(){
  41. const directives = [
  42. {
  43. name:'slice',
  44. value:this.value,
  45. expression:'value',
  46. arg:5,
  47. modifiers:{
  48. number:true,
  49. }
  50. }
  51. ]
  52. return (
  53. <div>
  54. 使用对象展开的方式
  55. <input {...{directives}}/>
  56. {this.value}
  57. </div>
  58. )
  59. }
  60. }
  61. </script>

过滤器

  1. <!-- 正常使用过滤器 -->
  2. <div>{{ msg | capitalize }}</div>
  3. <!-- 在jsx中使用过滤器 -->
  4. <div>{ this.$options.filters['capitalize'](this.msg)}</div>

示例

  1. <script>
  2. // <template>
  3. // <div> {{ msg | capitalize }}</div>
  4. // </template>
  5. export default {
  6. data(){
  7. return{
  8. msg : 'wula'
  9. }
  10. },
  11. filters:{
  12. capitalize(value){
  13. if(value) return "我过滤器"
  14. }
  15. },
  16. render(){
  17. console.log(this,'filter')
  18. console.log(this.$options,'filter')
  19. return (
  20. <div>{this.$options.filters['capitalize'](this.msg)}</div>
  21. )
  22. }
  23. }
  24. </script>

插槽

普通书写方式和具名插槽

子组件书写示例

  1. <script>
  2. export default {
  3. render(){
  4. return (
  5. <div>
  6. <header>
  7. {this.$slots.header}
  8. </header>
  9. 123546
  10. <main>
  11. {this.$slots.default}
  12. </main>
  13. </div>
  14. )
  15. }
  16. }
  17. </script>

父组件使用插槽

  1. <script>
  2. import jsxSlot from './components/jsx-slot'
  3. export default {
  4. components:{
  5. jsxSlot,
  6. },
  7. render(){
  8. return(
  9. <div>
  10. 普通插槽与具名插槽
  11. <jsx-slot>
  12. <i>我是默认插槽</i>
  13. <strong slot="header">我是头部</strong>
  14. </jsx-slot>
  15. </div>
  16. )
  17. }
  18. }
  19. </script>

作用域插槽

子组件书写示例

  1. <script>
  2. export default {
  3. data(){
  4. return {
  5. msg:"我是作用域插槽的内"
  6. }
  7. },
  8. render(){
  9. return (
  10. <div>
  11. 作用域插槽
  12. {this.$scopedSlots.default({
  13. msg:this.msg,
  14. })}
  15. </div>
  16. )
  17. }
  18. }
  19. </script>

父组件示例

  1. <script>
  2. import jsxSlot2 from './components/jsx-slot2'
  3. export default {
  4. components:{
  5. jsxSlot2,
  6. },
  7. render(){
  8. return(
  9. <div>
  10. 作用域插槽
  11. <jsx-slot2 {...{scopedSlots:{default:(props) => props.msg}}}>
  12. </jsx-slot2>
  13. </div>
  14. )
  15. }
  16. }
  17. </script>

jsx利用变量名生成一个元素

示例代码

  1. <script>
  2. export default {
  3. render(){
  4. const tag = "h1";
  5. return(
  6. <tag></tag>
  7. )
  8. }
  9. }
  10. </script>

演示案例
父组件代码

  1. <template>
  2. <base-demo :level="level"> 标题 </base-demo>
  3. </template>
  4. <script>
  5. import baseDemo from "./components/baseDemo";
  6. export default {
  7. name: "App",
  8. components: {
  9. baseDemo,
  10. },
  11. data() {
  12. return {
  13. level: "1",
  14. };
  15. }
  16. }
  17. </script>

子组件代码

  1. <script>
  2. export default {
  3. props:{
  4. level:{
  5. type:String,
  6. required:true,
  7. }
  8. },
  9. render(){
  10. const tag = 'h' + this.props.level
  11. return(
  12. <tag>
  13. {this.$slots.default}
  14. </tag>
  15. )
  16. }
  17. }
  18. </script>