,这个时候table下直接使用组件是无效的,可以使用特殊的属性挂载组件,即 is=“my-component”。
组件间传递数据常用父子组件传值过程汇总: 最常用:props、$emit
props
$emit
父组件
子组件
不推荐使用,vue.js 1.x的非父子通信:$broadcast、$dispatch
$broadcast
$dispatch
有监听的父组件
有监听的子组件
推荐使用:vue.js 2.x中非父子通信方式:使用一个空的Vue实例作为中央事件总线(bus)
bus.$emit
bus.$on
bus.$on
bus.$emit
组件A
bus
组件B
不推荐使用:父链,子链
$children
$parent
所有父组件
所有子组件
推荐你使用:子组件索引
$refs
子组件
父组件
props基础示例:<div id="app"> <my-component warning-text="提示信息"></my-component> </div> <script> Vue.component('my-component', { props: ['warningText'], template: '<div>{ {warningText}}</div>' }) var app = new Vue({ el: "#app" }) </script>
运行结果:
传递来自父级的动态数据,使用指令v-bind语法糖: ,当父级数据变化,也会传递给子组件。如下示例:
<div id="app"> <input type="text" v-model="parentMessage"> <my-component :message="parentMessage"></my-component> </div> <script> Vue.component('my-component', { props: ['message'], template: '<div>{ {message}}</div>' }) var app = new Vue({ el: "#app", data: { parentMessage: '1234' } }) </script>
运行结果:

关于传递数据的特点
<div id="app"> <h2 v-text="text"></h2> <h2 is="my-component7" message-kkk="[1,2,3]"></h2> <h2 is="my-component7" :message-kkk="[1,2,3]"></h2> </div> <script> Vue.component("my-component7", { props: ["messageKkk"], template: '<div>{ {messageKkk.length}}</div>' }); new Vue({ el: '#app', data: { text: '如果你要直接传递数字、布尔值、数组、对象,而且不使用 v-bind \ ,传递的仅仅是字符串,尝试下面的示例来对比:\n\ <h2 is="my-component7" message-kkk="[1,2,3]"></h2>\ <h2 is="my-component7" :message-kkk="[1,2,3]"></h2>', } }); </script>
注:字符串和数组长度的区别 运行结果:

props数据验证:
Vue.component('my-component', { props: { // 必须是数字类型 propA: Number, // 必须是数字或字符类型 propB: [String, Number], // 布尔值,如果没有定义,默认值是true propC: { type: Boolean, default: true }, // 数字类型,而且必传 propD: { type: Number, required: true }, // 如果数组或对象类型,默认值必须是一个函数来返回 propE: { type: Array, default: function(){ return [] } }, // 自定义一个验证函数 propF: { validator: function(value){ return value > 10; } } }, })
type的类型可以是:String、Number、Boolean、Object、Array、Function
$emit基础示例:<div id="app10"> <h2 v-text="text"></h2> <p>总数 : { {total}} </p> <my-component10 @increase="handleGetTotal" @reduce="handleGetTotal"> </my-component10> </div> <script> Vue.component("my-component10", { template: '<div><button @click="handleIncrease"> + l </button><button @click= "handleReduce ">-1</button></div>', data() { return { counter: 0 } }, methods: { handleIncrease: function () { this.counter++; this.$emit('increase', this.counter); }, handleReduce: function () { this.counter--; this.$emit('reduce', this.counter); }, } }); new Vue({ el: '#app10', data: { text: '子组件有两个按钮,分别实现加 1 和减 l 的效果 , 在改变组件的 data “ counter",\ 把它传递给父组件, 父组件用 v-on:increase 和 v-on:reduce ', total: 0 }, methods: { handleGetTotal: function (total) { this.total = total; } } }); </script>
运行结果:

使用v-model,简化父子组件双向绑定案例:
<div id="app12"> <h2 v-text="text"></h2> <p>父组件total:{ {total}}</p> 子组件total:<h2 is="my-component12" v-model="total"></h2> <button @click="add">增</button> </div> <script> Vue.component('my-component12', { props: ['value'], template: '<input v-model="value" @input="updateValue" />', methods: { updateValue: function (event) { this.$emit('input', event.target.value); } } }) new Vue({ el: "#app12", data: { text: "v-model 还可以用来创建自定义的表单输入组件, 进行数据双向绑定", total: 0 }, methods: { add: function () { this.total++; } } }); </script>
运行结果:

bus的使用<div id="app13"> <h2 v-text="text"></h2> 收到的信息:{ {message}} <component-a></component-a> </div> <script> var bus = new Vue(); Vue.component('component-a', { template: '<button @click="handleEvent">传递事件</button>', methods: { handleEvent: function () { bus.$emit('on-message', ' 来自组件 component-a 的内 容 '); } } }); new Vue({ el: '#app13', data: { text: '推荐使用一个空的 Vue 实例作为中央事件总线( bus ),也就是一个中介', message: '' }, mounted: function () { var _this = this; bus.$on('on-message', function (msg) { this.message = msg; }); } }); </script>
点击按钮后的结果:

使用$refs子组件索引Vue提供了子组件索引的方法,用特殊的属性ref为子组件指定一个索引名称。
<div id="app13"> <button @click="handleRef">通过ref获取子组件实例</button> <p>获取到的子组件数据:{ {tempMsg}}</p> <component-a ref="comA"></component-a> </div> <script> Vue.component('component-a', { template: '<div>子组件</div>', data: function(){ return { message: '子组件内容' } } }); new Vue({ el: '#app13', data: { tempMsg:'' }, methods: { handleRef:function(){ this.tempMsg = this.$refs.comA.message; } } }); </script>
点击按钮后的执行结果:

使用slot分发内容例子:
<app> <menu-main></menu-main> <menu-sub></menu-sub> <div class="container"> <menu-left></menu-left> <container></container> </div> <app-footer></app-footer> </app>
如上组件嵌套,就会使用到slot,这个叫内容分发。有两个特点:
- 不知道他的挂载点会有什么内容。
- 组件很可能有自己的模板。
基础示例:
<div id="app18"> <component-a> <p>分发的内容</p> <p>更多分发的内容</p> </component-a> </div> <script> Vue.component('component-a', { template: '\ <div>\ <slot>\ <p>如果父组件没有插入内容,默认显示这个</p>\ </slot>\ </div>' }); new Vue({ el: '#app18' }); </script>
运行结果:

具名Slot可以指定分发多个内容
<div id="app19"> <component-a> <h2 slot="header">标题</h2> <p>分发的内容</p> <p>更多分发的内容</p> <div slot="footer">底部</div> </component-a> </div> <script> Vue.component('component-a', { template: '<div class="container">\ <div class="header">\ <slot name="header"></slot>\ </div>\ <div class="main">\ <slot></slot>\ </div>\ <div class="footer">\ <slot name="footer"></slot>\ </div>\ </div>' }); new Vue({ el: '#app19' }); </script>
运行结果:

作用域插槽<div id="app20"> <book-list :books="books"> <template slot="book" scope="props"> <li>{ {props.bookName}}</li> </template> </book-list> </div> <script> Vue.component('book-list', { props: { books: { type: Array, default: function () { return []; } } }, template:'<ul>\ <slot name="book" v-for="book in books" :book-name="book.name">\ </slot>\ </ul>' }); new Vue({ el: '#app20', data: { books: [ { name:'javascript设计模式'}, { name:'javascript权威指南'}, { name:'javascript入门到放弃'} ] } }); </script>
注::book-name=“book.name” 与 props.bookName对应 运行结果:

访问slotvue2.X 提供了用来访问slot分发内容的方法$slots,如下示例:
<div id="app19"> <component-a> <h2 slot="header">标题</h2> <p>分发的内容</p> <p>更多分发的内容</p> <div slot="footer">底部</div> </component-a> </div> <script> Vue.component('component-a', { template: '<div class="container">\ <div class="header">\ <slot name="header"></slot>\ </div>\ <div class="main">\ <slot></slot>\ </div>\ <div class="footer">\ <slot name="footer"></slot>\ </div>\ </div>', mounted: function(){ var header = this.$slots.header; var main = this.$slots.default; var footer = this.$slots.footer; console.log(footer); // [fe] console.log(footer[0].elm.innerHTML); // 底部 } }); new Vue({ el: '#app19' }); </script>
运行结果:

组件的高级应用递归组件示例如下:
<div id="app19"> <child-component></child-component> </div> <script> Vue.component('child-component', { props: { count: { type: Number, default: 1 } }, template: '<div class="child">\ <p>第{ {count}}层子组件</p>\ <child-component\ :count="count+1"\ v-if="count < 3"></child-component>\ </div>' }); new Vue({ el: '#app19' }); </script>
注: 必须各一个条件显示递归数量,否则会抛出错误:max stack size exceeded 运行结果:

内联模板vue提供了一个内联模板的功能,在使用组件是,给标签使用inline-template特性,组件就会把内容当做模板,而不是内容分发。示例如下:
<div id="app19"> <child-component inline-template> <div> <h1>父组件中的子组件模板</h1> <p>{ { message}}</p> <p>{ { msg}}</p> <p>{ { commonData}}</p> </div> </child-component> </div> <script> Vue.component('child-component', { data: function () { return { msg: '子组件声明的数据', commonData: '同名数据,子组件数据' } } }); new Vue({ el: '#app19', data: { message: '父组件声明的数据', commonData: '同名数据,父组件数据' } }); </script>
注: 在父组件声明的数据message和子组件声明的msg,两个都会被渲染。如果同名,子组件数据优先使用!

动态组件Vue提供了一个特殊的元素,用来动态挂载不同组件,使用is特性来选择要挂载的组件。示例如下:
<div id="app19"> <component :is="currentView"></component> <button @click="handleChangeView('A')">切换comA组件</button> <button @click="handleChangeView('B')">切换comB组件</button> <button @click="handleChangeView('C')">切换comC组件</button> </div> <script> new Vue({ el: '#app19', components: { comA: { template: '<h1>组件A</h1>' }, comB: { template: '<h1>组件B</h1>' }, comC: { template: '<h1>组件C</h1>' } }, data: { currentView: 'comA', }, methods: { handleChangeView: function(component){ this.currentView = 'com' + component; } } }); </script>
运行效果:

异步组件<div id="app18"> <component-a></component-a> </div> <script> Vue.component('component-a', function(resolve,reject){ window.setTimeout(function(){ resolve({ template: '<div>我是异步组件渲染的</div>' }) }, 2000) }); new Vue({ el: '#app18' }); </script>
注: setTImeout是为了掩饰异步,工厂函数接收一个resolve回调。也可以调用reject(reason)加载失败。 运行结果:

其他$nextTick$nextTick:用来知道什么时候DOM更新完毕。异步更新DOM,当DOM没更新完时,div还没被创建。 实例如下:
<div id="app18"> <div id="div" v-if="showDiv">这是一段文字</div> <button @click="getText">获取文本内容</button> </div> <script> new Vue({ el: '#app18', data: { showDiv: false }, methods: { getText: function(){ this.showDiv = true; // var text = document.getElementById('div').innerHTML; // 报错了,因为未找到元素document.getElementById('div')为null,所以innerHTML属性访问出错。 // console.log(text) this.$nextTick(function(){ var text = document.getElementById('div').innerHTML; console.log(text) // 这是一段文字 }) } } }); </script>
运行结果自己试下!!!
本篇完。。。有问题联系我改。
|
还没有评论,来说两句吧...