4

组件概念

image
概念:该图中间块作为入口组件,那么挂载在入口组件的template下的组件是入口组件的子组件(图中的header组件等)

1、局部组件

三步口诀:声子,挂子,用子

  1. 声明一个局部组件,变量名首字母大写(为了和H5标签做区分),里面的内容和vue实例化对象的内容相似,但是不需要el,data必须是一个函数,函数返回一个对象
  2. 把组件挂载到入口文件的components对象中。
  3. 在入口文件的template中使用,可以是双闭合标签也可以是单闭合标签

2、全局组件

Vue.component(name,options)
第一个参数是组件的名称
第二个参数是组件的对象
注意全局组件要在创建Vue实例化对象前,否则会报错
image

 // 全局组件(要在创建Vue实例之前)
 Vue.component('Vbtn', {
 template: `<button>全局按钮组件</button>`
 })
 // 1、创建一个入口组件
 // 2、创建头部组件,侧边栏组件和内容组件
 var Heard = {
 template: `
 <div>
 <h2>我是头部组件</h2>
 <Vbtn></Vbtn>
 </div>
 `
 }
 var Aside = {
 template: `
 <div>我是侧边栏组件</div>
 `
 }
 var Content = {
 template: `
 <div>我是内容组件</div>
 `
 }
 var App = {
 template: `
 <div class="main">
 <Heard class = "heaed"></Heard>
 <div class="main2">
 <Aside class="aside"></Aside>
 <Content  class="content"/>
 </div>
 </div>
 `,
 components: {
 Heard,
 Aside,
 Content
 }
 }
 new Vue({
 el: "#app",
 data() {
 return {
 msg: "这是测试"
 }
 },
 template: `
 <App></App>
 `,
 components: {
 App
 }
 });

3、组件深入

问:为什么要通过父亲获取数据,在传递到子组件呢?
答:通过父亲向后端获取数据,然后在分发到各组件可以减少后端的交互,不然各个组件都向后端发送请求影响性能
见下图:
image

父子组件传值(父传子)

1、父用子时通过绑定自定义属性传递,
2、子要声明props:['属性']接收父绑定的自定义属性
3、收到就是自己的随便用

  • 在template中直接使用
  • 在js中this.属性名

    image

小补充:绑定自定义属性时:常量传递直接用,变量传递加冒号

总结父传子

父用子:先声子、挂子、用子
父传子:父传子(属性)、子声明(接收)、子使用

子传父

1、父用子绑定自定义事件
2、子触发自定义事件:this.$emit()

第一个参数是**自定义事件名**
第二个参数是**传递进去的值**

image
image

全局组件的数据传递

1、通过VUE内置组件slot分发内容

原因:如果不使用slot无法修改全局组件的内容
作用:slot元素作为承载分发内容的出口

2、父子传值

自定义属性传递常量直接使用不需要加冒号
image
如果要触发原生的事件需要通过 @原生事件名.native调用
image

3、具名插槽

在子组件中声明使用vue的内置组件:
<slot name = "one"></slot>
父组件中调用
<h2 slot= "one"></h2>
这样做的目的:可以一条数据一个坑,数据不会乱了

平行组件间传值

image
注意:要把$emit 和$on挂载到公共的vue实例中
$emit参数:第一参数是自定义的方法名,第二个参数是要传的值
$on参数:第一个是传过来的方法名,第二个是回调函数,用来处理数据
例:

 <div id="App">
        <Com_a></Com_a>
        <Com_b></Com_b>
        <Com_c></Com_c>
    </div>
    <script src="../node_modules/vue/dist/vue.min.js"></script>
    <script>
        var Event = new Vue();
        var Com_a = {
            template: `
            <div>
            <p>
                我是a的数据
                <button @click = "sent">将a的数据发送给c</btton>    
                </p>
            
            </div>
            `,
            data() {
                return {

                    a: "a数据"
                }
            }, methods: {
                sent() {
                    Event.$emit("msg_a", this.a)

                }
            }

        }
        var Com_b = {
            template: `
            <div>
            <p>
            我是b的数据
            <button @click = "sent">将b的数据发送给c</btton> 
            </p>
               
            </div>
            `,
            data() {
                return {
                    b: "b数据"
                }

            },
            methods: {
                sent() {
                    Event.$emit("msg_b", this.b)
                }
            }

        }
        var Com_c = {
            template: `
            <div>
            <p>
                <span>我是c的数据接收到:</span>
                <span>{{a}}</span>
                </p>
                <p>
                <span>我是c的数据接收到:</span>
                <span>{{b}}</span>
                </p>  
            </div>
            `,
            data() {
                return {
                    a: "",
                    b: ""
                }

            },
            mounted() {
                Event.$on("msg_b", (val) => {
                    this.b = val;
                });
                Event.$on("msg_a", (val) => {
                    this.a = val;
                });
            }

        }
        new Vue({
            el: "#App",
            data() {

            },
            components: {
                Com_a,
                Com_b,
                Com_c
            }
        })
    </script>

附加功能

1、过滤器

组件过滤器filters

1、作用:对当前数据添油加醋
2、语法:声明在组件内使用filters对象,返回一个函数,函数一定要有返回值
3、调用:template中调用过滤器:数据属性|过滤器名字

var Content = {
     template: `
         <div>
         <input type = number  v-model = "msg"/>
         <h2>{{msg|RmbData}}</h2>
         </div>
     `,
     data(){
         return{
            msg:10
         }
     },
     filters:{
         RmbData(value){
            return '$'+value
         }
     }
 }

全局过滤器filter

语法:Vue.filter(过滤器名字,回调函数)
过滤器传参:
默认第一个参数是管道符前的数值,调用的时候不需要传进去
image
image

2、监听器watch

一次只能监听一个属性
基本数据类型-简单监听
复杂数据类型-深度监听
image

3、计算属性computed

可以同时监听多个属性
默认只有getter
对象返回一个函数
image

setter的实现
和methods比较

1、计算属性有缓存,methods 没有
2、计算属性直接绑定属性不需要调用,methods要通过事件去调用

生命周期

详见图解
imageimage

特别说明

1、
beforeUpdate 数据更新前,操作虚拟DOM

官网原文:
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期### activated间更改状态。如果要相应状态改变,通常最好使用计算属性watcher 取而代之。

不清晰问题点:
image
2、activated、deactivated
结合Vue的内置 组件:<keep-alive>使用,可以将组件缓存,防止频繁的创建和销毁的组件
3、附生命周期练习代码:

<!DOCTYPE html>

<html lang="en">

<head>

 <meta charset="UTF-8">

 <meta name="viewport" content="width=device-width, initial-scale=1.0">

 <title>生命周期</title>

</head>

<body>

 <script src="../node_modules/vue/dist/vue.js"></script>

 <div id="app">

 <App/>

 </div>

 <script>

 // beforeCreated

 var Test = {

 data() {

 return {

 msg:"生命周期"

 }

 },

 template:`<div class= "main" id = "d1" >

 <input  v-model = "msg"/>

 <h2> {{msg}}</h2>

 </div>`

 ,

 beforeCreate(){

 console.log(this.msg)

 },

 created(){

 console.log(this.msg);

 this.msg += "--1"

 },

 beforeMount(){

 let d1= document.getElementById("app");

 console.log(d1);

 },

 mounted(){

 let d1= document.getElementById("app");

 console.log(d1);

 },

 beforeUpdate(){

 // data里的值看不出变化,和实际DOM看不出变化:

 // console.log(document.getElementById("app"));

 // console.log("修改后数据:"+this.msg);

 // 看得出变化:

 console.log(document.getElementById("app").innerHTML);

 },

 updated(){

 // data里的值看不出变化,和实际DOM看不出变化:

 // console.log(document.getElementById("app"));

 // console.log("修改后数据:"+this.msg);

 // 看得出变化:

 console.log(document.getElementById("app").innerHTML);

 },

 beforeDestroy(){

 console.log("beforeDestroy")

 },

 destroyed(){

 console.log("destroyed")

 },

 activated(){

 console.log("被激活了")

 },

 deactivated(){

 console.log("被停用了")

 }

 }

 var App = {

 data() {

 return {

 msg:"生命周期",

 isShow:true

 }

 },

 template: `

 <div>

 <keep-alive>

 <Test v-if="isShow"></Test>

 </keep-alive> 

 <button @click="changelife" >改变生死</button>

 </div>

 `, 

 components:{

 Test

 },

 methods: {

 changelife() {

 this.isShow = !this.isShow

 }

 }

 }

 new Vue({

 el:"#app",

 data() {

 return {

 msg:"生命周期",

 isShow:true

 }

 },

 components:{

 App

 }

 })

 </script>

</body>

</html>

一声蔷薇udVkP
25 声望3 粉丝

未来可期