中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue如何通過JSX動態渲染組件

發布時間:2022-12-06 09:10:50 來源:億速云 閱讀:133 作者:iii 欄目:編程語言

這篇文章主要介紹“Vue如何通過JSX動態渲染組件”,在日常操作中,相信很多人在Vue如何通過JSX動態渲染組件問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue如何通過JSX動態渲染組件”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、明確需求

有一組數組結構如下:

const arr = [ 
  { tag: 'van-field' },  // 輸入框
  { tag: 'van-cell' },   // 彈出層
  { tag: 'van-stepper' } // 步進器
]

想通過循環arr,拿到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>

2.3 JSX動態渲染組件

父組件

<van-cell  v-for="(cell, cellKey) in arr" :key="cellKey" >
  <!-- 用jsx動態渲染  -->
  <RendTag :cell="cell" />
</van-cell>

const arr = [ 
  { tag: 'van-field' },  // 輸入框
  { tag: 'van-cell' },   // 彈出層
  { tag: 'van-stepper' } // 步進器
]

子組件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: '請輸入姓名',
                    "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一樣渲染成我們想要的組件。

三、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='custom-div'>這是自定義的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}>

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>
    );
  }
};

3.2.4 監聽事件、事件修飾符

監聽事件

監聽事件想到用 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動態渲染組件”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

嘉禾县| 峨边| 龙江县| 达孜县| 佛坪县| 恭城| 双鸭山市| 内黄县| 昌图县| 铜陵市| 昌乐县| 新化县| 禹城市| 郎溪县| 孝昌县| 乐安县| 双江| 桓台县| 泸水县| 建平县| 麻阳| 冷水江市| 榆林市| 顺义区| 木兰县| 洮南市| 崇仁县| 莲花县| 金门县| 石家庄市| 右玉县| 任丘市| 上犹县| 蒙阴县| 铁岭县| 阿克| 凤凰县| 太仓市| 务川| 诸暨市| 和静县|