@@ -95,7 +95,7 @@ slot分为3种类型,第一种是普通插槽,也就是我们上边提到这
9595
9696上边案例中,close-icon这个关闭按钮的事件函数是绑定在close这个元素上边,而且是在组件内部绑定的。刚才我们实现了close-icon的替换,假如UI这边需要调整close-icon的位置,最快的方法是改样式,改样式首先需要考虑这个组件大概那些地方会用到,是全局改样式还是只是改局部的,如果不是使用第三方组件的情况下,也就是咱们从开发一个组件的方面考虑,适应常用场景下保证组件灵活性,避免使用者使用的时候需要对组件内部进行修改。所以我们这里使用slot-scope来对上边的案例进行一个修改。
9797
98- <iframe height =" 265 " style =" width : 100% ;" scrolling =" no " title =" message-box-2 " src =" //codepen.io/uncleze2017/embed/ewWZGv/?height=265&theme-id=0&default-tab=result " frameborder =" no " allowtransparency =" true " allowfullscreen =" true " >
98+ <iframe height =" 400 " style =" width : 100% ;" scrolling =" no " title =" message-box-2 " src =" //codepen.io/uncleze2017/embed/ewWZGv/?height=265&theme-id=0&default-tab=result " frameborder =" no " allowtransparency =" true " allowfullscreen =" true " >
9999 See the Pen <a href='https://codepen.io/uncleze2017/pen/ewWZGv/'>message-box-2</a> by uncleze
100100 (<a href='https://codepen.io/uncleze2017'>@uncleze2017</a>) on <a href='https://codepen.io'>CodePen</a>.
101101 </iframe >
@@ -125,9 +125,107 @@ slot分为3种类型,第一种是普通插槽,也就是我们上边提到这
125125```
126126将close这个方法用slot-scope传递到了父组件,让使用这可以自定义元素并绑定事件函数,解决之前只能在内部固定绑定事件的情况。
127127
128- ## 行为与表象分离
128+ ## 无渲染组件
129129
130130我们通过slot和slot-scope给使用这提供部分自定义html和调用自己内部实现的函数的途径。让使用者自定义部分html,然后还能方便的调用函数,并且不用理会内部的状态。
131131
132- 其实我们仔细想想,就上述的组件,其实完全可以让用户自定义全部的html,也就是组件不渲染html,只提供函数,和组件的状态。
132+ 所谓的无渲染组件,就是让用户自定义全部的html,组件只提供函数,和组件的状态等剩余内容,即是不渲染html的组件。
133+
134+ 接下来我们使用最开始提到的案例。
135+
136+ 因为已经不需要渲染了html了, 所以template就不需要了,我们直接使用render函数来进行渲染
137+
138+ ``` js
139+ Vue .component (' renderless-component' , {
140+ render (h ) {
141+ return this .$scopedSlots .default ({
142+ tags: this .tags ,
143+ addTag: this .addTag ,
144+ deleteTag: this .deleteTag
145+ })
146+ },
147+ props: {
148+ tags: Array
149+ },
150+ mounted () {
151+ console .log (this .tags )
152+ },
153+ methods: {
154+ addTag (e ) {
155+ let value = e .target .value .trim ()
156+ if (! this .tags .includes (value)) {
157+ this .tags .push (value)
158+ }
159+ e .target .value = ' '
160+ this .$emit (' on-change' ,value, this .tags )
161+ },
162+ delTag (index ) {
163+ this .tags .splice (index, 1 )
164+ }
165+ }
166+ })
167+
168+ let vue = new Vue ({
169+ el: ' #app' ,
170+ data () {
171+ return {
172+ tags: [
173+ ' 日本' ,
174+ ' 泰国'
175+ ]
176+ }
177+ },
178+ methods: {
179+ handleChangeTags (cur , tags ) {
180+ console .log (cur, tags)
181+ }
182+ }
183+ })
184+ ```
185+
186+ ``` html
187+ <div id =" app" >
188+ <renderless-component :tags =" tags" >
189+ <div class =" input-tag" slot-scope =" {tags, addTag, deleteTag}" >
190+ <span class =" tag" v-for =" (tag, i) in tags" :key =" i" >
191+ {{tag}}
192+ <a href =" javascript:;" @click =" delTag(i)" >× ; </a >
193+ </span >
194+ <input type =" text" @keydown.enter =" addTag" >
195+ </div >
196+ </renderless-component >
197+ </div >
198+ ```
199+ <iframe height =" 400 " style =" width : 100% ;" scrolling =" no " title =" renderless-component " src =" //codepen.io/uncleze2017/embed/Prmaev/?height=265&theme-id=0&default-tab=result " frameborder =" no " allowtransparency =" true " allowfullscreen =" true " >
200+ See the Pen <a href='https://codepen.io/uncleze2017/pen/Prmaev/'>renderless-component</a> by uncleze
201+ (<a href='https://codepen.io/uncleze2017'>@uncleze2017</a>) on <a href='https://codepen.io'>CodePen</a>.
202+ </iframe >
203+
204+ 然后,我们调整一下html部分,就可以适应第二种场景。
205+
206+ ``` html
207+ <div id =" app" >
208+ <renderless-component :tags =" tags" >
209+ <div class =" input-tag__wrapper" slot-scope =" {tags, addTag, delTag}" >
210+ <div class =" input-tag" >
211+ <input type =" text" @keydown.enter =" addTag" >
212+ </div >
213+ <div class =" tag-list" v-if =" tags.length" >
214+ <span class =" tag" v-for =" (tag, i) in tags" :key =" i" >
215+ {{tag}}
216+ <a href =" javascript:;" @click =" delTag(i)" >× ; </a >
217+ </span >
218+ </div >
219+ <div class =" tag-list__empty" v-else >
220+ Please add some tags ...
221+ </div >
222+ </div >
223+ </renderless-component >
224+ </div >
225+ ```
226+
227+ <iframe height =" 300 " style =" width : 100% ;" scrolling =" no " title =" renderless-component2 " src =" //codepen.io/uncleze2017/embed/zVwXXr/?height=265&theme-id=0&default-tab=result " frameborder =" no " allowtransparency =" true " allowfullscreen =" true " >
228+ See the Pen <a href='https://codepen.io/uncleze2017/pen/zVwXXr/'>renderless-component2</a> by uncleze
229+ (<a href='https://codepen.io/uncleze2017'>@uncleze2017</a>) on <a href='https://codepen.io'>CodePen</a>.
230+ </iframe >
133231
0 commit comments