Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

青灯夜游
풀어 주다: 2022-12-05 18:53:43
앞으로
2923명이 탐색했습니다.

Vue는 어떻게 JSX를 통해 구성 요소를 동적으로 렌더링합니까? 다음 기사에서는 Vue가 JSX를 통해 구성 요소를 효율적으로 동적으로 렌더링하는 방법을 소개합니다. 도움이 되기를 바랍니다.

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

1. 명확한 요구 사항

동적 구성 요소를 렌더링하는 방법은 무엇입니까? [관련 권장 사항: vuejs 비디오 튜토리얼]

다음과 같은 배열 구조 집합이 있습니다.

const arr = [ 
  { tag: 'van-field' },  // 输入框
  { tag: 'van-cell' },   // 弹出层
  { tag: 'van-stepper' } // 步进器
]
로그인 후 복사

arr을 반복하여 tag 렌더링에 해당하는 구성 요소를 가져오고 싶습니다. tag渲染对应的组件。

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

下面我们分析如何写才是最优。

二、进行分析

2.1 v-if走天下

我们可以写一个v-for去循环arr数组,然后通过v-if去判断tag,渲染对应的组件类型。

这样子写不是不可以,只不过扩展性不好,每次加一个标签,模板就要再加一个v-if。

我相信很多人起初都是这样写。

但这不是我们优雅人该写的代码。

2.2 动态渲染组件标签

我们能不能根据tag的标签来渲染出真正的标签。

关键是循环内,怎么根据遍历的tag去渲染出真正的组件。

<van-cell  v-for="(cell, cellKey) in arr" :key="cellKey" >
      <!-- 动态渲染  -->
</van-cell>
로그인 후 복사

有请今天的主角JSX上场。

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

2.3 JSX动态渲染组件

父组件


  
  


const arr = [ 
  { tag: &#39;van-field&#39; },  // 输入框
  { tag: &#39;van-cell&#39; },   // 弹出层
  { tag: &#39;van-stepper&#39; } // 步进器
]
로그인 후 복사

子组件RendTag.vue

<script>
const AssemblyRend = {
  name: "assembly-rend",
  props: ["cell"],
  data() {
    return {
      input: "",
    };
  },
  methods: {
    onClick() {
      this.$emit("changeTag", this.input);
    },
  },
  computed:{
    itemVal:{
      get(){
        return this.cell.value
      },
      set(v){
        this.cell.value = v
      }
    }
  },
  render() {
    const { cell } = this; // 解构
    const assembly = cell.tag;  // 这里就是我们动态渲染组件的核心 

    return (
        <assembly
          v-model={this.itemVal}
          placeholder={cell.placeholder}
          min={cell.min}
          onClick={this.onClick}
        >
        </assembly>
      );
  },
};

export default {
  name: "RendTag",
  props: {
    cell: {
        type: Object,
        default:()=>{
            return {
                {
                    "title": "能否输入",
                    placeholder: &#39;请输入姓名&#39;,
                    "value": "name",
                    "tag": "van-switch",
                }
            }
        }
    },
  },
  methods: {
    changeTag(val) {},
  },
  render() {
    const { cell } = this; // 解构
    return (
      <div class="rendTag-content">
        <AssemblyRend
          cell={cell}
          onChangeTag={this.changeTag}
        ></AssemblyRend>
      </div>
    );
  },
};
</script>
로그인 후 복사

我们利用JSX的render可以写JavaScript返回组件,来实现我们动态渲染标签。

render相当于我们vue中的模板。

于是渲染出的效果如下:根据tag渲染成真正的组件

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

我们用普通的组件,无法像JSX一样渲染成我们想要的组件。

这里的v-model用计算属性的坑,我推荐看一遍:实战v-model如何绑定多循环表达式(内含原理)

其实这两篇是有一定的挂钩的,只不过我在这里拆开了需求。

主要也是方便朋友们阅读理解。

三、vue中如何使用JSX

借着该需求,我们恶补一下JSX。

3.1 是什么?

JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javascript 的灵活性,同时又兼具 html 的语义化和直观性。

活度强的部分组件可以用JSX来代替(比如以上需求);
整个工程没有必要都使用JSX。

3.2 基本用法

3.2.1 函数式组件

我们在组件中,也可以嵌入ButtonCounter组件。

const ButtonCounter = {
  name: "button-counter",
  props: ["count"],
  methods: {
    onClick() {
      this.$emit("changeNum", this.count + 1);
    }
  },
  render() {
    return <button onClick={this.onClick}>数量:{this.count}</button>;
  }
};

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      count: 0
    };
  },
  methods: {
    // 改变button按钮数量
    changeNum(val) {
      this.count = val;
    }
  },
  render() {
    const { count } = this; // 解构
    return (
      <div class="hello-world-content">
        <ButtonCounter style={{ marginTop: "20px" }} count={count} onChangeNum={this.changeNum}></ButtonCounter>
      </div>
    );
  }
};
로그인 후 복사

3.2.2 普通属性、行内样式、动态class与style

可以看到,其实和vue的模板写法基本一致,只不过要注意的是花括号;

在vue的模板是要写两对花括号,而在JSX只需要写一对

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      count: 0,
      text: "Hello World!",
      msgClass: "msg-class",
      isGreen: true
    };
  },
  render() {
    const { count, text } = this; // 解构
    return (
      <div class="hello-world-content">
        <p class={this.msg ? this.msgClass : ""}>动态绑定class</p>
        <p style={this.isGreen ? "color: green" : ""}>动态绑定style</p>
      </div>
    );
  }
};
로그인 후 복사

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

3.2.3 常用指令

v-html、v-if、v-for、v-model常用指令在JSX中无法使用,需要使用其他方式来实现。

v-html

在JSX中,如果要设置DOM的innerHTML,需要用到domProps

组件使用:

<HelloWorld 
   msg="<div class=&#39;custom-div&#39;>这是自定义的DOM</div>"> 
</HelloWorld>
로그인 후 복사

组件代码:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {};
  },
  methods: {},
  render() {
    return <div domPropsInnerHTML={this.msg}></div>;
  }
};
로그인 후 복사

渲染DOM结果:

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

v-for

使用map来实现:

render() {
  const list = [1,2,3]
  return( 
    <div>
      { list.map(item => <button>按钮{item}</button>) }
    </div>
  )
}
로그인 후 복사

v-if

简单示例:用三元

render() {
    const bool = false;
    return <div>{bool ? <button>按钮1</button> : <button>按钮2</button>}</div>;
}
로그인 후 복사

复杂示例:直接用JS

render() {
  let num = 3
  if(num === 1){ return( <button>按钮1</button> ) }
  if(num === 2){ return( <button>按钮2</button> ) }
  if(num === 3){ return( <button>按钮3</button> ) }
}
로그인 후 복사

v-model

直接使用:<input v-model={this.value}>

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

아래 최적의 글쓰기 방법을 분석합니다.

둘째, 분석하기

2.1 v-if로 전 세계를 여행한다면

< code>v-for는 arr 배열을 반복한 다음 v-if를 사용하여 태그를 결정하고 해당 구성요소 유형을 렌더링합니다.

🎜이렇게 작성하는 것이 불가능하지는 않지만 확장성이 좋지 않습니다. 태그를 추가할 때마다 템플릿에 v-if를 추가해야 합니다. 🎜🎜처음에는 이렇게 쓴 분들이 많았던 것 같아요. 🎜🎜하지만 이것은 우리 우아한 사람들이 작성해야 할 코드가 아닙니다. 🎜

🎜2.2 구성 요소 태그를 동적으로 렌더링🎜

🎜tag의 태그를 기반으로 실제 태그를 렌더링할 수 있나요? 🎜🎜핵심은 루프 내에서 탐색된 태그를 기반으로 실제 구성 요소를 렌더링하는 방법입니다. 🎜
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      value: "abc"
    };
  },
  watch: {
    value(val) {
      console.log("this.model内容:" + val);
    }
  },
  methods: {},
  render() {
    return (
      <div>
        <input v-model={this.value} placeholder="普通文本" />
      </div>
    );
  }
};
로그인 후 복사
🎜 오늘의 주인공 JSX가 출연하도록 초대받았습니다. 🎜🎜Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.🎜

🎜2.3 JSX 동적 렌더링 구성 요소🎜

🎜상위 구성 요소🎜
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {};
  },
  methods: {
    handleClick(val) {
      alert(val);
    }
  },
  render() {
    return (
      <div>
        <button type="button" onClick={this.handleClick.bind(this, 11)}>
          方式一
        </button>
        <button type="button" onClick={() => this.handleClick(22)}>
          方式二
        </button>
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사
🎜하위 구성 요소 RendTag.vue🎜
methods: {
    input(e) {
      this.value = e.target.value;
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} onInput={this.input} />
      </div>
    );
  }
로그인 후 복사
로그인 후 복사
🎜JSX의 render를 사용하여 JavaScript를 작성할 수 있습니다. 태그의 동적 렌더링을 구현하는 구성요소입니다. 🎜🎜render는 우리 vue의 템플릿과 동일합니다. 🎜🎜그래서 렌더링 효과는 다음과 같습니다: 태그에 따라 실제 구성 요소로 렌더링됩니다🎜🎜Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.🎜🎜JSX처럼 원하는 컴포넌트로 렌더링할 수 없는 일반 컴포넌트를 사용합니다. 🎜🎜여기의 v-model은 계산된 속성을 사용합니다. 실용적인 v-model 다중 루프 표현식 바인딩 방법(원리 포함)🎜🎜🎜사실 이 두 글은 어느 정도 관련이 있지만 요구 사항을 세분화했습니다. 여기. 🎜🎜주로 친구들의 읽기와 이해를 돕기 위한 것입니다. 🎜

3. vue에서 JSX를 사용하는 방법🎜🎜이러한 요구를 JSX로 보완하겠습니다. 🎜

🎜3.1이란 무엇인가요? 🎜

🎜JSX는 Javascript의 구문 확장인 JSX = Javascript + XML입니다. 이는 Javascript로 XML을 작성한다는 의미입니다. JSX의 이러한 기능으로 인해 Javascript의 유연성을 가지게 됩니다. HTML의 의미와 직관성. 🎜
🎜활동성이 강한 일부 구성 요소는 JSX로 대체될 수 있습니다(예: 위의 요구 사항).
전체 프로젝트에 JSX를 사용할 필요는 없습니다. 🎜

🎜3.2 기본 사용법🎜

🎜3.2.1 기능 구성 요소🎜🎜🎜현재 위치 구성 요소에는 ButtonCounter 구성 요소가 포함될 수도 있습니다. 🎜
<input 
  type="text" 
  value={this.value} 
  onInput={(e) => (this.vaue = e.target.value)} 
/>
로그인 후 복사
로그인 후 복사

🎜3.2.2 공통 속성, 인라인 스타일, 동적 클래스 및 스타일🎜🎜🎜 보시다시피 기본적으로 Vue의 템플릿 작성 방법과 동일하지만, 🎜🎜vue 템플릿에서는 두 쌍의 중괄호를 작성해야 하지만 JSX에서는 🎜한 쌍🎜만 작성하면 됩니다. 🎜
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      value: ""
    };
  },
  watch: {
    value(val) {
      console.log("this.model的内容:" + val);
    }
  },
  methods: {
    handleInput(e) {
      this.value = e.target.value;
    },
    handleFocus(e) {
      console.log(e.target);
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} {...{ on: { input: this.handleInput, focus: this.handleFocus } }} />
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사
🎜Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.🎜< h4 data-id="heading-11">🎜3.2.3 공통 명령어 🎜🎜🎜v-html, v-if, v-for, v-model 공통 명령어는 JSX에서 사용할 수 없으며 다른 방법으로 구현해야 합니다. . 🎜🎜🎜v-html🎜🎜🎜JSX에서 DOM의 innerHTML을 설정하려면 domProps를 사용해야 합니다. Component Usage : 🎜
{...{nativeOn:{click: this.handleClick}}}
로그인 후 복사
로그인 후 복사
e🎜component 코드 : 🎜
if (event.target !== event.currentTarget){
  return
}
로그인 후 복사
로그인 후 복사
🎜rendered dom 결과 : 🎜🎜 Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.🎜🎜🎜v-for🎜🎜🎜map을 사용하여 구현: 🎜
if(event.keyCode === 13) {
  // 执行逻辑
}
로그인 후 복사
로그인 후 복사
🎜🎜v-if🎜🎜🎜간단한 예: 사용 삼항 🎜
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  methods: {
    handleClick(e) {
      console.log("click事件:" + e.target);
    },
    handleInput(e) {
      console.log("input事件:" + e.target);
    },
    handleMouseDown(e) {
      console.log("mousedown事件:" + e.target);
    },
    handleMouseUp(e) {
      console.log("mouseup事件" + e.target);
    }
  },
  render() {
    return (
      <div
        {...{
          on: {
            // 相当于 :click.capture
            "!click": this.handleClick,
            // 相当于 :input.once
            "~input": this.handleInput,
            // 相当于 :mousedown.passive
            "&mousedown": this.handleMouseDown,
            // 相当于 :mouseup.capture.once
            "~!mouseup": this.handleMouseUp
          }
        }}
      >
        点击模块
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사
🎜복잡한 예: JS🎜
<HelloWorld>
    <template slot="default">默认内容</template>
    <template slot="footer">
      <el-button type="primary">确定</el-button>
      <el-button>取消</el-button>
    </template>
</HelloWorld>
로그인 후 복사
로그인 후 복사
🎜🎜v-model🎜🎜🎜직접 사용: <input v-model={this.value}>🎜
export default {
  name: "HelloWorld",
  render() {
    return (
      <div>
        <div class="default">{this.$slots.default}</div>
        <div class="footer">{this.$slots.footer}</div>
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사
🎜🎜3.2 . 4 Listening events and event modifiers🎜🎜🎜🎜Listening events🎜🎜🎜onChange, onClick 등을 사용하여 이벤트를 수신하는 것을 생각합니다. 🎜

需要注意的是,传参数不能使用 onClick={this.handleClick(params)},这样子会每次 render的时候都会自动执行一次方法。

应该使用bind,或者箭头函数来传参。

组件示例代码:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {};
  },
  methods: {
    handleClick(val) {
      alert(val);
    }
  },
  render() {
    return (
      <div>
        <button type="button" onClick={this.handleClick.bind(this, 11)}>
          方式一
        </button>
        <button type="button" onClick={() => this.handleClick(22)}>
          方式二
        </button>
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사

用监听事件来实现v-model:

methods: {
    input(e) {
      this.value = e.target.value;
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} onInput={this.input} />
      </div>
    );
  }
로그인 후 복사
로그인 후 복사

也可以调整为:

<input 
  type="text" 
  value={this.value} 
  onInput={(e) => (this.vaue = e.target.value)} 
/>
로그인 후 복사
로그인 후 복사

还可以使用对象的方式去监听事件:解构事件

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      value: ""
    };
  },
  watch: {
    value(val) {
      console.log("this.model的内容:" + val);
    }
  },
  methods: {
    handleInput(e) {
      this.value = e.target.value;
    },
    handleFocus(e) {
      console.log(e.target);
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} {...{ on: { input: this.handleInput, focus: this.handleFocus } }} />
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사

nativeOn仅对于组件,用于监听原生事件,也可以使用对象的方式去监听事件:

{...{nativeOn:{click: this.handleClick}}}
로그인 후 복사
로그인 후 복사

事件修饰符

和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用。

  • .stop : 阻止事件冒泡,在JSX中使用event.stopPropagation()来代替
  • .prevent:阻止默认行为,在JSX中使用event.preventDefault() 来代替
  • .self:只当事件是从侦听器绑定的元素本身触发时才触发回调,使用下面的条件判断进行代替
if (event.target !== event.currentTarget){
  return
}
로그인 후 복사
로그인 후 복사

.enter与keyCode: 在特定键触发时才触发回调

if(event.keyCode === 13) {
  // 执行逻辑
}
로그인 후 복사
로그인 후 복사

除了上面这些修饰符之外,尤大大对于.once,.capture,.passive,.capture.once做了优化,简化代码:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  methods: {
    handleClick(e) {
      console.log("click事件:" + e.target);
    },
    handleInput(e) {
      console.log("input事件:" + e.target);
    },
    handleMouseDown(e) {
      console.log("mousedown事件:" + e.target);
    },
    handleMouseUp(e) {
      console.log("mouseup事件" + e.target);
    }
  },
  render() {
    return (
      <div
        {...{
          on: {
            // 相当于 :click.capture
            "!click": this.handleClick,
            // 相当于 :input.once
            "~input": this.handleInput,
            // 相当于 :mousedown.passive
            "&mousedown": this.handleMouseDown,
            // 相当于 :mouseup.capture.once
            "~!mouseup": this.handleMouseUp
          }
        }}
      >
        点击模块
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사

3.3 插槽

3.3.1 普通插槽与具名插槽

父传子。

示例:

<HelloWorld>
    <template slot="default">默认内容</template>
    <template slot="footer">
      <el-button type="primary">确定</el-button>
      <el-button>取消</el-button>
    </template>
</HelloWorld>
로그인 후 복사
로그인 후 복사

HelloWorld组件代码:this.$slots

export default {
  name: "HelloWorld",
  render() {
    return (
      <div>
        <div class="default">{this.$slots.default}</div>
        <div class="footer">{this.$slots.footer}</div>
      </div>
    );
  }
};
로그인 후 복사
로그인 후 복사

3.3.2 作用域插槽

子传父。

示例:

<HelloWorld>
    <template v-slot:content="{ name, age }">
      <div>姓名:{{ name }}</div>
      <div>年龄:{{ age }}</div>
    </template>
</HelloWorld>
로그인 후 복사

HelloWorld组件代码:this.$scopedSlots

export default {
  name: "HelloWorld",
  render() {
    return (
      <div>
        <div class="content">{this.$scopedSlots.content({ name: "张三", age: 20 })}</div>
      </div>
    );
  }
};
로그인 후 복사

子组件通过{this.$scopedSlots.content({ name: "张三", age: 20 })}指定插槽的名称为content,并将含有name,age属性的对象数据传递给父组件,父组件就可以在插槽内容中使用子组件传递来的数据。

看到v-html用innerHTML;v-for用map;.stop用event.stopPropagation()
你有什么感想?
这不就是我们JavaScript方法的操作吗。
所以JSX就是Javascript + XML。

Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.

后记

我以前一直觉得Vue中没必要用JSX吧,用模板Template足以了。

但经过这个需求,我想JSX在处理动态渲染组件还是蛮占有优势的?。

日后面试官问我JSX在Vue的有什么应用场景,我想我可以把这个需求说一说。

(学习视频分享:web前端开发编程基础视频

위 내용은 Vue가 JSX를 통해 구성 요소를 동적으로 렌더링하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿