<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] >[success] # 渲染函數(render函數)和JSX快速掌握 在接下來講學習到如何在 **Vue** 中使用 **渲染函數** 來 **創建視圖模板** ,并且會講解 **JSX** 的 **語法** ,同時會補充2個內容,第一是 **函數式組件** ,第二是 **作用域插槽** 。 >[success] ## render函數 **render函數** :可以用 **函數的方式** 渲染 **dom元素** 到頁面中。 下面會講解2種使用場景: 1. 在 **main.js** 中如何使用 2. 在 **.vue** 文件中使用 >[success] ### render函數在main.js中使用 **src/main.js** ~~~ import Vue from 'vue' import App from './App.vue' // app組件 import router from './router' import store from './store' import './plugins/element.js' import Bus from './lib/bus' // 引入Bus Vue.config.productionTip = false Vue.prototype.$bus = Bus // 掛載Bus到Vue原型鏈(全局掛載Bus) new Vue({ router, store, render: h => h(App) // 渲染app組件 }).$mount('#app') ~~~ 我們首先在 **main.js** 中學習 **render函數** , **render** 的 **屬性值** 是一個 **回調函數** ,它的參數可以用括號包裹起來,例如這樣: **render: (h) => h(App)** ,如果 **只有一個參數就可以不用括號包裹** , **h這個參數是一個方法** ,這個方法能 **創建一個虛擬節點** ,**這個函數 return 返回一個結果** 。 | 方法名 | 參數 | 是否必填 | | --- | --- | --- | | **render函數:render: h => h(App)** | **h函數的第1個參數**:**要渲染的組件,或者一個標簽字符串,或者也可以是一個函數** | **是** | | | **h函數的第2個參數**: 該參數是一個 **配置對象**,可以 **通過該對象給元素設置屬性** ,例如 **div** 標簽的 **id、class 等等** | **否** | | | **h函數的第3個參數**:該 **參數可以是字符串或者數組**,主要作用是 **給元素添加內容** | **否** | 1. **h函數的參數1** **說明** : **第1個參數** 是用來傳入 **元素標簽** 或者 **組件** 。 1.1. **傳入組件** :**main.js** 中 **h函數** 默認傳入的是 **app.vue頁面組件**,所以就會 **渲染該組件** ,下面引入之前封裝的 **CountTo 組件** ~~~ import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import './plugins/element.js' import Bus from './lib/bus' import CountTo from '_c/count-to' // 引入CountTo 組件 Vue.config.productionTip = false Vue.prototype.$bus = Bus new Vue({ router, store, render: h => h(CountTo, { // 'class': 'count-to', // 給組件最外層盒子添加class類名 // 或者這樣寫 // 'class': ['count-to', true ? 'count-to2' : ''], // 或者這樣寫 'class': { 'count-to': true, 'count-to2': 1 === 1, }, attrs: {}, // 定義屬性id等等 style: {}, // 定義樣式 props: { // 添加屬性 這里可以理解為就是<count-to :endValue="100"/> endValue: 100 }, // domProps: { // dom的一些屬性 // innerHTML: '11' // 可以設置標簽的一些內容 // }, on: { // 添加事件 'on-animation-end': (val) => { // 事件名 console.log(val) } }, nativeOn: { // 組件內沒有定義click事件時,給組件最外層元素綁定一個click事件 'click': () => { console.log('click') } }, directives: [], // 可以定義自定義指令 scopedSlots: {}, slot: '', // 插槽 key: '', // 設置一個值讓每個組件的key不相等 ref: '' // ref }) }).$mount('#app') ~~~ 1.2. **傳入字符串** :也可以像下面寫,這樣頁面中就 **渲染** 出一個 **div標簽** 。 ~~~ new Vue({ router, store, render: h => h('div') }).$mount('#app') ~~~ 1.3. **傳入函數** : ~~~ let func = ()=> 'h3' new Vue({ router, store, render: h => h(func()) }).$mount('#app') ~~~ 2. **h函數的參數2** **說明** : **h函數** 的 **第2個參數是個對象** ,用來 **定義元素的一些屬性** 。 2.1. **給元素設置屬性** : ~~~ new Vue({ router, store, render: h => h('div', { attrs: { // 添加屬性 id: 'box' }, style: { // 添加樣式 color: 'red' } }) }).$mount('#app') ~~~ 3. **h函數的參數3** **說明** : **h函數的第3個參數可以是字符串或者數組** ,用來 **定義元素的內容** 。 3.1. **傳入字符串** ~~~ new Vue({ router, store, render: h => h('div', { attrs: { // 添加屬性 id: 'box' }, style: { // 添加樣式 color: 'red' } }, '我是div的內容') }).$mount('#app') ~~~ **如果不設置樣式可以直接忽略h函數的第2個參數** , 直接寫內容 ~~~ new Vue({ router, store, render: h => h('div', '123') }).$mount('#app') ~~~ 3.2. **傳入數組** 如果想讓內容是 **多個標簽** ,就需要 **傳入數組** ~~~ new Vue({ router, store, render: h => h('div', [ h('span', '111'), h('span', '222') ]) }).$mount('#app') ~~~ 3.3. **循環傳入標簽** 如果想實現一個類似 **v-for** 的效果,首先先看 **正常循環列表寫法** ~~~ <template> <ul @click="handleClick"> <li @click.stop="handleClick" v-for="(item, index) in list" :key="`list_item_${index}`">{{ item.name }} </li> </ul> </template> <script> export default{ data(){ return{ list: [ {name: '小明'}, {name: '小黑'} ] } }, methods: { handleClick(event){ console.log(event) } } } </script> ~~~ 接下來使用 **render函數** 實現上面的 **循環列表跟點擊事件** ~~~ // 點擊事件 const handleClick = event => { console.log(event) event.stopPropagation() } // 數據 let list = [ {name: '小明'}, {name: '小黑'} ] // 循環生成li const getLiEleArr = (h) => { return list.map((item, index) => h('li', { on: { 'click': handleClick }, key: `list_item_${index}` }, item.name)) } // 最終渲染 new Vue({ router, store, render: h => h('div',[ h('ul', { on: { 'click': handleClick } }, getLiEleArr(h)) ]) }).$mount('#app') ~~~ >[success] ### render函數在.vue中使用 有時 **即使你封裝好了組件,但是想根據自己的方式去定制組件內的元素以及內容**,這時候就需要 **給組件傳入一個render函數** 1. **父組件** 首先在 **路由列表** 的 **路由對象** 中添加新創建的 **render-page** 頁面配置路由 **src/router/router.js** ~~~ export default [ { path: '/render-page', name: '/render_page', component: () => import('@/views/render-page') } ] ~~~ 然后在 **src/views/render-page.vue** 頁面 **引入list組件** **src/views/render-page.vue** ~~~ <template> <div> <list :list="list" :render="renderFunc"></list> </div> </template> <script> import List from '_c/list' export default{ data(){ return{ list: [ // 數據 {name: '小明'}, {name: '小黑'} ] } }, components: { List }, methods: { renderFunc(h, name){ // 自定義render函數渲染自己想要的dom節點內容 return h('i', { style: { color: 'pink' } }, name) } } } </script> ~~~ 1. **子組件** **src/components/list/list.vue** ~~~ <template> <ul> <li v-for="(item, index) in list" :key="`item_${index}`"> <!-- 如果未傳入render函數就span標簽內容 --> <span v-if="!render">{{ item.name }}</span> <!-- 如果傳入了render函數,就使用render函數自定義dom的節點來渲染 --> <render-dom v-else :render-func="render" :name="item.name"></render-dom> </li> </ul> </template> <script> // 引入函數式組件 import RenderDom from '_c/render-dom' export default { name: 'List', components: { RenderDom // 注冊函數式組件 }, props: { list: { // 列表內容 type: Array, default: () => [] }, render: { // render 函數 type: Function, default: () => {} } } } </script> ~~~ 定義一個 **index.js 方便父組件引用** **src/components/list/index.js** ~~~ import List from './list.vue' export default List ~~~ 在上面的組件中使用到了 **函數式組件** ,這里寫的 **函數式組件** 就是使用 **reder函數 自定義一些想要的標簽** 然后 **return** 返回一個 **虛擬節點** , **最終渲染在使用函數式組件的地方** ,**函數式組件詳解看下方的文檔介紹**。 **src/components/render-dom.js** ~~~ export default { functional: true, props: { name: String, // 組件渲染的文字內容 renderFunc: Function // 傳入的render函數 }, /** * render渲染函數 * @param {Function} h - render函數的回調方法,用于生成dom節點 * @param {Object} ctx - 指代當前的這個對象 */ render: (h, ctx) => { return ctx.props.renderFunc(h, ctx.props.name) } } ~~~ >[success] ## 函數式組件 **函數式組件** : **只給它傳入數據,它不做任何響應式的操作, 不監聽傳遞給它的狀態** ,這個組件 **沒有生命周期和鉤子函數**,它 **只是作為一個接收參數的函數** , 當 **functional 設置為 true** 時候,證明 **它是一個沒有狀態的組件,也沒有實例,就是一個對象** , 當 **把這個對象引入到其他頁面,當做一個組件去使用的時候,vue會把它做一個處理,會把 【render函數】里面邏輯返回的【虛擬節點】做一個渲染** 。 **src/components/render-dom.js** ~~~ export default { functional: true, props: { name: String, // 組件渲染的文字內容 renderFunc: Function // 傳入的render函數 }, /** * render渲染函數 * @param {Function} h - render函數的回調方法,用于生成dom節點 * @param {Object} ctx - 指代當前的這個對象 */ render: (h, ctx) => { return ctx.props.renderFunc(h, ctx.props.name) } } ~~~ >[success] ## JSX **JSX** :**JSX** 最先是 **react** 提出的, **通過一種形式,在 js 里面寫 html 標簽,還有一些特定的語法** ,最后會把這個 **字符串** 轉譯成 **js** ,去用 **render函數** 來做渲染。 >[success] ### JSX渲染標簽字符串 1. **父組件** **src/views/render-page.vue** ~~~ <template> <div> <list :list="list" :render="renderFunc"></list> </div> </template> <script> import List from '_c/list' export default{ data(){ return{ list: [ // 數據 {name: '小明'}, {name: '小黑'} ] } }, components: { List }, methods: { renderFunc(h, name){ // 自定義render函數渲染自己想要的dom節點內容 /** * render函數方式 */ // return h('i', { // style: { // color: 'pink' // } // }, name) /** * JSX方式 * JSX與template模板對比 * style: * template的標簽中寫法:style="{ color: 'pink' }" * JSX寫法:style={{color: 'pink'}} * JSX中style不需要添加雙引號,屬性都需要用{}包裹 * * 事件: * template的標簽中寫法v-click="handleClick" 或者 @click="handleClick" * JSX寫法on-click={ this.handleClick } */ return ( <i on-click={ this.handleClick } style={{color: 'pink'}}>{ name }</i> ) }, handleClick(event){ console.log(event) } } } </script> ~~~ 使用 **JSX** 時 **render函數** 的 **形參必須是 h** ,不可以改成其他的(例如 **createElement**)。以上代碼中引入的 **List組件** 在上面的 **render函數** 文檔中有寫過,在此處就不再過多陳述。 >[success] ### JSX渲染組件 1. **父組件** **src/views/render-page.vue** ~~~ <template> <div> <list :list="list" :render="renderFunc"></list> </div> </template> <script> import List from '_c/list' import CountTo from '_c/count-to' // 引入組件 export default{ data(){ return{ list: [ // 數據 { number: 100 }, { number: 45 } ] } }, components: { List }, methods: { renderFunc(h, number){ // 自定義render函數渲染自己想要的dom節點內容 return ( /** * 這里可以引入組件進行渲染,而且不用在components對象中注冊 * 事件分為2種:原生事件、自定義事件 * html標簽:支持原生事件 * 組件:支持原生事件(給下面的CountTo組件綁定一個原生click事件,就相當于給組件內的最外層元素綁定了一個click事件, * 寫法:nativeOn-事件名稱={方法})、 * 自定義事件(寫法:on-自定義事件名稱={方法}) * template模板中的事件修飾符在JSX跟render函數中用到需要看文檔 * */ <CountTo nativeOn-click={this.handleClick} on-on-animation-end={this.handleEnd} endValue={number} style={{color: 'pink'}}></CountTo> ) }, handleClick(event){ console.log(event) }, handleEnd(){ console.log('end!') } } } </script> ~~~ 父組件中引入的 **[CountTo組件](http://www.hmoore.net/wangjiachong/vue_notes/1971966)** 2. **子組件** **src/components/list.vue** ~~~ <template> <ul> <li @mousemove="handleMove" v-for="(item, index) in list" :key="`item_${index}`"> <!-- 如果未傳入render函數就span標簽內容 --> <span v-if="!render">{{ item.number }}</span> <!-- 如果傳入了render函數,就使用render函數自定義dom的節點來渲染 --> <render-dom v-else :render-func="render" :number="item.number"></render-dom> </li> </ul> </template> <script> // 引入函數式組件 import RenderDom from '_c/render-dom' export default { name: 'List', components: { RenderDom // 注冊函數式組件 }, props: { list: { // 列表內容 type: Array, default: () => [] }, render: { // render 函數 type: Function, default: () => {} } }, methods: { handleMove(event){ // 阻止默認行為(文字不可以選中復制) event.preventDefault() } } } </script> ~~~ **list組件** 對應的 **index.js**,用于 **父組件方便引用** **src/components/list/index.js** ~~~ import List from './list.vue' export default List ~~~ **子組件** 中用到的 **函數式組件 render-dom.js** **src/components/render-dom.js** ~~~ export default { functional: true, props: { number: Number, // 組件渲染的文字內容 renderFunc: Function // 傳入的render函數 }, /** * render渲染函數 * @param {Function} h - render函數的回調方法,用于生成dom節點 * @param {Object} ctx - 指代當前的這個對象 */ render: (h, ctx) => { return ctx.props.renderFunc(h, ctx.props.number) } } ~~~ >[success] ## 作用域插槽 **定制組件內的元素以及內容** ,用 **render函數** 以及 **JSX** 都比較繁瑣,接下來用 **作用域插槽** 來實現這個需求。 1. **父組件** **src/views/render-page.vue** ~~~ <template> <div> <list :list="list"> <h3 slot="aa">我是小明</h3> <coun-to slot-scope="count" :end-value="count.number"></coun-to> </list> </div> </template> <script> import List from '_c/list' import CounTo from '_c/count-to' // 引入組件 export default{ data(){ return{ list: [ // 數據 { number: 100 }, { number: 45 } ] } }, components: { List, CounTo } } </script> ~~~ 2. **子組件** **src/components/list.vue** ~~~ <template> <ul> <li v-for="(item, index) in list" :key="`item_${index}`"> <!-- 默認插槽 --> <!-- <slot></slot> --> <!-- 具名插槽 --> <slot name="aa"></slot> <!-- 作用域插槽 --> <slot :number="item.number"></slot> </li> </ul> </template> <script> export default { name: 'List', props: { list: { // 列表內容 type: Array, default: () => [] } } } </script> ~~~ 3. **插槽總結** 3.1 **匿名插槽** 應用場景:**組件內** 只需要一個 **插槽** 的情況,可以使用 **匿名插槽** 。 3.2 **具名插槽** 應用場景:**組件內** 需要多個 **插槽** 的情況,可以使用 **具名插槽** 。 3.3 **作用域插槽**應用場景:**父組件插槽插入的內容中** 使用到了 **組件內的數據** 。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看