VUE 之 组件
组件是为了解决页面布局的。
什么是单页面?
答:整个页面的切换都是在这个页面上进行变化的,没有页面的刷新。
1、全局组件
1.1全局组件流程: 1.创建全局组件======>创建一个Vue实例
<div id="app"> <global-component></global-component> # 第一种渲染<global-component>的方法。流程:1>全局组件中有一个global-component参数,此时就开始查。2>查到new Vue中的app有
</div> # global-component标签,此时就会将data中的数据传给template中进行替换。由于自定义的标签在<div id='app'>中包着,所以生成的页 <script> # 也有div包着 Vue.component("global-component",{ template:`<div><h1>{{name}}</h1></div>`, data(){ return { name:'我叫小沈阳' } } }); new Vue({ el:'#app', // template:`<global-component></global-component>` # 第二种渲染方法 由于Vue根实例中有了template来承载自定义的标签,div顶部中就不需要写自定义标签了。而此时就会把Vue }) # 实例中自定义的标签作为根,在这个标签中进行渲染数据。
2、局部组件
局部组件实际上就是创建了一个JavaScript object
局部组件的执行流程: 创建一个局部组件(let 变量)=====>然后创建一个Vue根实例。 =====>创建一个入口app来承载本来应该在Vue实例中的代码,为了是代码更加清晰。
内部的三大步骤:创建局部组件====>注册(components)=====>使用
<div id='app'>
</div>
let Header = { template:`<div><h1>{{greeting}}</h1></div>`, # let Header 就是创建一个局部组件,内部除了没有el属性,其他属性都可以写。必须要有承载标签的template data(){ return{ greeting:'HELLO World' } } }; let App = { # 创建一个App入口,内部注册一个app_header标签指向Header,然后用template承载该标签。 template:`<div><app_header></app_header></div>`, components:{ app_header:Header } }; new Vue({ # 创建一个Vue根实例 注册一个 属性名:指向App,在template中承载该标签。 el:"#app", template:`<div><APP></APP></div>`, components:{ APP:App } })
3、父子组件通信
父组件如何给子组件传送数据
<div id="app"> </div> <script> let Son = { 1、# 先定义自一个局部组件 template:`<div> <h1>{{greeting}}</h1> <h2>{{father}}</h2> 7、#将数据交给template进行渲染 </div>`, props:['father'], 6、# 子组件中通过props:[],这种形式来接收父组件传送来的数据 data(){ return{ greeting:'Hello World' } } }; let App = { 2、# 再定义一个入口组件注册局部组件 template:`<div> <my_son v-bind:father="fatherData"></my_son> 5、# 给注册的属性绑定一个字定义属性,father </div>`, components:{ my_son:Son }, data(){ 4、# 将数据赋值给自定义的属性father return{ fatherData:'Who are you!' } } }; new Vue({ 3、# 创建一个Vue实例,注册所有组件的入口组件 el:"#app", template:`<App></App>`, components:{ App } }) </script>
4、子父组件的通信
子组件如何将数据传送给父组件
业务要求:点击子组件让父组件的字体变大
<div id="app"></div> <script> let Son = { 1、# 创建一个子组件 template:`<div> <button @click="Son_Click">点我就会变大</button> </div>`, methods:{ 9、# 只要绑定事件就用methods,然后通过this.$emit('自定义父组件中的事件',参数) Son_Click:function () { this.$emit('change_size',0.1) } } }; let Father = { 2、# 创建一个入口父组件 template:`<div> <span :style="{fontSize:postFontSize + 'em'}">我是你爸爸</span> 11、# 通过参数的传递使得字体发生变化,在template中渲染出来。 <my_son @change_size="fatherClick"></my_son> 5、# 生成自定义的标签,并绑定一个自定义的点击事件,这个change_size就是自定义的,相当于 </div>`, click,父组件绑定字定义点击事件是用来监听父组件是否发生变化 components:{ 4、# 注册子组件 my_son:Son }, data(){ 6、# 传送数据,设定posFontSize 默认字体大小为1 return{ postFontSize:1 } }, methods:{ 7、# 由于绑定了事件,所以要用methods方法,然后自定义一个fatherClick函数 赋值给自定义事件 fatherClick:function (value) { 10、# value 用来接收子组件传过来的参数。 this.postFontSize += value } } }; new Vue({ 3、# 创建一个Vue实例 el:'#app', template:`<Father></Father>`, components:{ Father } }) </script>
5、非子父之间通信(用中间调度器)
<script> let hanfei = new Vue(); // 中间调度器什么都不传 let B = { template: `<div> <h1>这是B</h1> <button @click="my_click">点我向A说话</button> </div>`, methods: { my_click: function () { console.log("马") // 向A说话 // 向中间调度器提交事件 hanfei.$emit("maweihua_say", "晚上等我一起吃饭~~~") // 组件向中间调度器提交过来的数据用$emit } } }; let A = { template: `<div><h1>这是A</h1>{{say}}</div>`, data(){ return { say: "" } }, mounted(){ // 监听中间调度器中的方法 let that = this; hanfei.$on("maweihua_say", function (data) { //中间调度器向组件提交数据的时候用$on console.log(data) that.say = data }) } }; const app = new Vue({ el: "#app", components: { A, B } }) </script>
6、混入(mixs)
由于有多个组件存在且有使用相同的可能是数据,也可能是方法时,就可以用混入mixs来封装这个数据或者方法,然后在其他组件调用即可。
<div id="app"></div> <script> let mixs = { # 由于都使用了show方法,所以创建一个mixs组件用来封装这些属性 methods: { show: function () { console.log('我来了') } } }; let A = { # 创建组件A
template: `<div> <button @click="show">点我</button> # 使用了show这个方法 </div>`, mixins: [mixs], # 通过固定搭配 mixins:[mixs]调用 mixs这个组件 }; let B = { # 创建组件B template: `<div> <button @mouseenter="show">触摸我</button> # 使用了show这个方法 </div>`, mixins: [mixs], }; new Vue({ # 创建Vue实例 el: "#app", template: `<div> <A></A> <B></B> </div>`, components: { A:A, B:B } }) </script>
7、插槽
插槽可以进行内容的分发,提高组件的复用性。相同的组件写多个块,就可以用插槽,写一个组件,然后通过slot进行内容分发,来提高复用性。
<div id="app"> <global-component>我佛</global-component> # 同相同的<global-component>标签可以写多个块 <global-component>慈悲</global-component> </div> <script> Vue.component("global-component",{ template:`<div><slot></slot></div>`, # 可以通过slot进行数据分发,将多个块中的内容,而不是标签分发给template进行渲染 }); new Vue({ el:'#app', }) </script>
8、具名插槽
也是插槽的一种,它是将所有的slot标签包在了自己定义的里边
<div id="app"> <global-component> <div slot="header">首页</div> <div slot="first">第一页</div> <div slot="second">第二页</div> </global-component> </div> <script> Vue.component("global-component",{ template:`<div> <slot name="header"></slot> # name 是slot中的夫定的写法 <slot name="first"></slot> <slot name="second"></slot> </div>`, }); new Vue({ el:'#app', }) </script>