Vue 框架学习(七) 组件化开发
一、组件通信
(一)传值(两结合使用详见案例)
1、父传子:props(注意4个名字两两成对)
父组件:使用绑定把值传给子组件
子组件:通过props获取父组件传入的值(可以进行类型限制或默认值)
<body> <div id="app"> <!-- 只能有一个root对象,所以数据的使用必须在一个div里面 --> <cpn :cmovies="moviese" :cmessage="message"></cpn> </div> <template id="cpn"> <div> <ul> <li v-for="movie in cmovies"> {{movie}} </li> </ul> <h2>{{cmessage}}</h2> </div> </template> <script> // 父传子: props const cpn = { template: '#cpn', // props: ['cmovies', 'cmessage'], props: { // 类型限制 // cmovies: Array, // cmessage: String // 提供默认值,以及毕传值,数组不能传空数组 cmovies: { type: Array, default: ['Default', 'Default'], }, cmessage: { type: String, default: 'Default', request: true, } }, data() { return {} }, } //创建Vue实例,得到 ViewModel const app = new Vue({ el: '#app', data: { message: 'Smallstars', moviese: ['海王', '火影'] }, methods: {}, computed: {}, components: { cpn }, }); </script> </body>
2、子传父
子组件:通过监听点击事件,然后使用$emit发射事件
父组件:监听子组件的发射事件
<body> <!-- 父组件模板 --> <div id="app"> <!-- 监听子组件发射的事件,传给父组件操作 --> <cpn @itemclick="cpnclick"></cpn> </div> <!-- 子组件模板 --> <template id="cpn"> <div> <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button> </div> </template> <script> // 子组件 const cpn = { template: '#cpn', data() { return { categories: [{ id: 1, name: '热门推荐' }, { id: 2, name: '手机数码' }, { id: 3, name: '家用家电' }, { id: 4, name: '电脑办公' }, ] } }, methods: { btnClick(item) { // 发射事件 this.$emit('itemclick', item) } }, } //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: {}, methods: { // 父组件对子组件传来的事件进行操作 cpnclick(item) { console.log('cpnclick', item); } }, computed: {}, components: { cpn }, }); </script> </body>
(二)访问
1、父访子
$children数组、$refs
<body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn ref="aaa"></cpn> <button @click="btnClick">按钮</button> </div> <template id="cpn"> <div>子组件</div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: { message: '你好啊', }, methods: { btnClick() { // 调用子组件的方法 // 1.$children // console.log(this.$children); // this.$children[0].showMessage(); // 2.$refs console.log(this.$refs.aaa); } }, computed: {}, components: { cpn: { template: '#cpn', methods: { showMessage() { console.log('showMessage'); } }, } }, }); </script> </body>
2、子访父
$parent、$root(访问根组件)
<body> <div id="app"> <cpn></cpn> </div> <template id="cpn"> <div> <h2>cpn子组件</h2> <ccpn></ccpn> </div> </template> <template id="ccpn"> <div> <h2>ccpn子组件</h2> <button @click="btnClick">按钮</button> </div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: { message: '你好啊我是Vue', }, methods: { }, computed: {}, components: { cpn: { template: '#cpn', data() { return { name: 'cpnName' } }, components: { ccpn: { template: '#ccpn', methods: { btnClick() { // 1.访问父组件 console.log(this.$parent); console.log(this.$parent.name); // 2. 访问根组件 console.log(this.$root.message); } }, } } } }, }); </script> </body>
(三)事件总线
(四)Vuex
详见Vuex专题
二、插槽
(一)普通插槽
<body> <div id="app"> <cpn></cpn> <cpn> <p>cpn2</p> </cpn> <cpn><span>cpn3</span></cpn> <cpn><input type="text"> <p>cpn4</p> </cpn> </div> <template id="cpn"> <div> <p>我是cpn</p> <slot><button>默认按钮</button></slot> </div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: {}, methods: {}, computed: {}, components: { cpn: { template: '#cpn' } }, }); </script> </body>
(二)具名插槽
<body> <div id="app"> <cpn><span>没有name属性会把所有没有名字的插槽都替换</span></cpn> <cpn><button slot="left">返回</button></cpn> <cpn><span slot="center">使用slot使用相应的插槽</span></cpn> </div> <template id="cpn"> <div> <slot>没有name</slot> <slot name="left">左</slot> <slot name="center">中</slot> <slot name="right">右</slot> <slot>没有name</slot> </div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: {}, methods: {}, computed: {}, components: { cpn: { template: '#cpn' } }, }); </script> </body>
(三)编译作用域(父组件和子组件的属性相同)
<body> <div id="app"> <!-- 先看在那个模板里面,直接去app找 --> <cpn v-show="isShow"></cpn> </div> <template id="cpn"> <div> <h2>我是子组件</h2> <!-- 模板中去自己模板中找 --> <button v-show="!isShow">按钮</button> </div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: { message: 'Smallstars', isShow: true, }, methods: {}, computed: {}, components: { cpn: { template: '#cpn', data() { return { isShow: false, } }, } }, }); </script> </body>
(四)作用域插槽(父组件替换插槽的内容,但内容是子组件决定。由于编译作用域的原因,父组件本不能直接访问子组件的值)
<body> <div id="app"> <cpn></cpn> <!-- 父组件想对子组件的数据进行操作,但是不能直接拿(前一章作用域问题) --> <!-- 获取子组件数据用不同方式展示 --> <cpn> <template slot-scope="slot"> <!-- <span v-for="item in slot.data">{{item}} - </span> --> <span>{{slot.data1.join('-')}}</span> </template> </cpn> <cpn> <template slot-scope="slot"> <span v-for="item in slot.data1">{{item}} * </span> </template> </cpn> </div> <template id="cpn"> <div> <!-- 作用域插槽,在这里绑定数据好在父组件使用 --> <slot :data1="pLanguages"> <ul> <li v-for="item in pLanguages">{{item}}</li> </ul> </slot> </div> </template> <script> //创建Vue实例,得到 ViewModel const vm = new Vue({ el: '#app', data: { message: 'Smallstars', }, methods: {}, computed: {}, components: { cpn: { template: '#cpn', data() { return { pLanguages: ['Python', 'JavaScript', 'C++', 'C#'] } }, } }, }); </script> </body>
每天进步一点点