Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)

目录

混入(mixins)好处

什么是组件,为什么要有组件&组件的好处(!!!)

组件语法,创建父子组件

组件传值/通信(!!!

组件通信的语法(!!!

生命周期&钩子函数概念&作用(!!!

一、混入(Mixin !)

明确需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ElNLdBrH-1590890282703)(images/1574832393768.png)]

说明:后期是多个页面,每个页面都new Vue

因此:就会出现举例普通方法冗余 同一段代码写了多次

解决:通过混入(mixin)从而提高代码复用性,减少冗余

语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
###局部
const 变量 = {
    data() {// 1通过data来存放公共数据,2留心之前data是对象,现在data是函数返回对象
        return {
            // 模型数据
        }
    },
    methods:{}    //  留心:方法中使用模型数据,先用newVue模型中的,再用混入模型中的
    //...
}

// 大家熟悉的语法
new Vue({
    mixins: [变量名,...,变量名]  // 作用:将公共代码混入进来,留心:变量名不能加引号 加引号就是字符串
    el,
    data: {},
    methods,
    computed,
    watch
})


###全局(不需要去new Vue整合 直接所有都可以
Vue.mixin({
    data,
    methods
    ...
})

来一个小练习

步骤1:创建两个Vue对象分别监控app1和app2

步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名

步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app1">
    <button @click="fn">点击弹框</button>
</div>

<div id="app2">
    <button @click="fn">点击弹框</button>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=神龙教主1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=神龙教主2和age=2模型数据 & 点击方法弹出模型中的姓名

const vm1 = new Vue({
    el: '#app1',
    data: {
        uname: "神龙教主1",
        age: 1
    },
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})

const vm2 = new Vue({
    el: '#app2',
    data: {
        uname: "神龙教主2",
        age: 2
    },
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})
</script>
</body>
</html>

发现:模型中的数据uname是不同的,但是methods中的方法代码一样,冗余

解决:通过mixin混入技术

代码1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app1">
    <button @click="fn">点击弹框</button>
</div>

<div id="app2">
    <button @click="fn">点击弹框</button>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

const mixinOne = {
    // data() { return {} }
    // methods: {}
    // computed: {}
    data() {
        return {
            uname: "张三"
        }
    },
    methods: {
        fn() {
            alert(this.uname)  // 先有自己的,自己的没有再用公共的
        }  
    }
}

const vm1 = new Vue({
    // 融合公共代码,减少代码冗余   留心切记别加引号
    mixins: [mixinOne],
    el: '#app1',
    data: {
        // uname: "小明1",
        age: 1
    },
})

const vm2 = new Vue({
    // 融合公共代码,减少代码冗余
    mixins: [mixinOne],
    el: '#app2',
    data: {
        uname: "小明2",
        age: 2
    },
})
</script>
</body>
</html>

代码2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app1">
    <button @click="fn">点击弹框</button>
</div>

<div id="app2">
    <button @click="fn">点击弹框</button>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

Vue.mixin({
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})

const vm1 = new Vue({
    el: '#app1',
    data: {
        uname: "小明1",
        age: 1
    },
})

const vm2 = new Vue({
    el: '#app2',
    data: {
        uname: "小明2",
        age: 2
    },
})
</script>
</body>
</html>

小总结

实战:用全局多,这样后期哪个页面要用就直接导入

混入(mixin):是vue提供的一个技术,顾名思义将代码混合到一起(提取)从而减少代码冗余,提高代码复用

语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
###全局
Vue.mixin({
    data() { return {} },
    methods
    ...
})

###局部
const 变量名 = {
    data() { return {} },
    methods
    ...
}
new Vue({
    mixins: [变量名,...,变量名],  // 切记别加引号
    el
    ...
})

二、组件(Component)

明确需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hiz6xjEz-1590890282712)(images/1574832927088.png)]

组件(Component)是vue最强大的功能之一

将一个大型网站划分成一个个更小的可控单元(一个个组件 里面放html、css、js)

思考:什么是组件

回答:就是一个文件(其实就是以前的html只不过语法不同了)里面存放html、js、css

思考:这样有什么好处?

回答:减少代码冗余,方便后期维护,因为它提出了一个概念,封装公共代码相互引用

语法

说明:组件很重要,但写项目语法会比这个简单很多 因为框架封装了

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###局部的 也就是说你要在new Vue中写
const vm = new Vue({
    el:
    //...
    components: {
        标签名: {
            template: `写HTML代码`,
            data() {return {}},
            methods
            //...
        }
    }
})

###全局的
Vue.component(标签名, {
    template: `放HTML代码`,  // template 模板 也就是html
    data() {return {}},
    methods: {}
    //...
})

调用

1
2
3
在【监控范围】内,直接写<标签名></标签名>

脚下留心:如果标签名大写,需要将大写改成-小写(因为HTML不识别大小写

组件的创建

  • 需求
1
2
自定义组件mytag1输出:<p>我叫MT1:T1</p>
自定义组件mytag2输出:<p>我叫MT2:T2</p>
  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <mytag1></mytag1>
    <mytag2></mytag2>
    <!-- <myTag3></myTag3> html不区分大小写 -->
    <my-tag3></my-tag3>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 自定义组件mytag1输出:<p>我叫MT1:T1</p>
// 自定义组件mytag2输出:<p>我叫MT2:T2</p>
Vue.component('mytag1', {
    template: `<p>我叫MT1:T1</p>`
})
Vue.component('mytag2', {
    template: `<p>我叫MT2:T2</p>`  //ES6模板字符串语法
})
Vue.component('myTag3', {
    template: `<p>webopen</p>`  
})

const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>

小总结

什么是组件:就是一个文件,里面放HTML、JS、CSS

组件好处:可以相互调用,减少代码冗余,便于后期维护

定义语法

1
2
3
4
5
6
7
Vue.component(标签名, {
    // 声明组件代码
    template: `放代码`,  // 1es6语法 2只能有一个根
    data() {return {} },
    methods
    ...
})

调用语法

1
在【监控范围】内调用<标签名></标签名>  留心:html不区分大小写,因此组件名大写改成【-小写】

组件中使用指令(渲染数据&事件)

  • 需求
1
2
3
自定义组件mytag1输出:<p>你好,MT,听说你年薪1w</p>
变量:name-MT,money-1
事件:p-click弹出hello,word
  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <!-- 这边双标签/单标签都行  最后能会替换成组件template里面的数据 -->
    <mytag1 />
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 自定义组件mytag1输出:<p>你好,MT,听说你年薪1w</p>
// 变量:name-MT,money-1
// 事件:p-click弹出hello,word
Vue.component('mytag1', { // 组件名随意但是留意大小写
    template: `
    <p @click="say">你好,{{name}},听说你年薪{{money}}w</p>
    `,
    data(){
        return {
            name: 'MT',
            money: 1
        }
    },
    methods: {
        say() {
            alert('hello,word')
        }
    }
})

const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>
  • 小总结
1
2
如何在组件中显示数据: 通过模板语法{{data中的键}}
如何在组件中使用事件: 通过事件语法@事件类型="函数名"

父子组件的创建

  • 需求
1
2
3
4
自定义组件mytag1输出:<p>你好,MT(退出),听说你很M</p>
变量:name-MT,age-100
事件:p-click弹出hello
注意:退出位置用a标签创建子组件
  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <mytag1 />
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 自定义组件mytag1输出:<p>你好,MT(退出),听说你很M</p>
// 变量:name-MT,age-100
// 事件:p-click弹出hello
// 注意:退出位置用a标签创建子组件
Vue.component('mytag1', {
    template: `<p @click="say">你好,{{name}}(<logout />),听说你很M,{{age}}岁了</p>`,
    data() {
        return {
            name: "MT",
            age: 100
        }
    },
    methods: {
        say() {
            alert('hello')
            alert(this.age)
        }
    },
    // 通过components来声明子组件  调用同之前的
    components: {
        // 键就是标签名 值是对象 内容一样
        logout: {
            template: `<a href="">退出</a>`
        }
    }
})

const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>

总结

什么是组件(作用):就是一个文件,存放HTML、CSS、JS

组件的好处:减少代码冗余、便于后期维护

创建组件语法:

1
2
3
4
5
6
7
8
Vue.component(标签名, { //留心:标签名后期调用如果有大写,改为【-小写】 因为html不识别大小写
    template:``  // 声明组件内容
    data() { return {} },
    methods: {},
    components: {}  //声明子组件 键就是子组件标签名,值是对象里面写template等
})

上述的components其实就是局部语法 也是一样 只不过不是在组件中写 而是new Vue中写

组件中如何渲染数据:{{data中的键}}

组件中如何调用事件:@click=“函数名”

三、动态组件(了解一下吧)
- 利用component标签和is属性实现

效果图

在这里插入图片描述

语法

步骤1:定义组件/页面,语法创建(注:也有简化语法

步骤2:在页面调用显示即可

代码

  1. 造导航 ul>li*4
  2. 造组件 4
  3. 显示组件
  4. 动态显示组件(点击导航切换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <ul>
        <li @click="chooseCompontent = 'index'">首页</li>
        <li @click="chooseCompontent = 'jiadian'">家电</li>
        <li @click="chooseCompontent = 'baojian'">保健</li>
        <li @click="chooseCompontent = 'meirong'">美容</li>
    </ul>
    <!--
        留心:咱们之前显示   <标签名 />
        现在:希望动态,点击导航改变 用 component标签

        <component is="index"></component>
        <component is="baojian"></component>
     -->
     <component v-bind:is="chooseCompontent"></component>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 造组件
Vue.component('index', {
    template: `<div>这是首页页面</div>`
})

Vue.component('jiadian', {
    template: `<div>这是家电页面</div>`
})

Vue.component('baojian', {
    template: `<div>这是保健页面</div>`
})

Vue.component('meirong', {
    template: `<div>这是美容页面</div>`
})


const vm = new Vue({
    el: '#app',
    data: {
        chooseCompontent: 'jiadian'
    }
})
</script>
</body>
</html>

四、组件通信/传值(!!!)

明确需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVfwf2Da-1590890282721)(images/1574925192507.png)]

加入商品组件里面触发点击事件,需要更改头部组件里面的数据

思考:如何实现

回答:通过组件通信技术

语法

父组件->子组件:通过props接受父传递数据

1
2
3
步骤1:子通过props键来接受父传递的数据  props:['变量名',...,'变量名']  
                                   #注:这么写就相当于在子组件data中声明数据了
步骤2:父传递给子   父在调用子的组件上通过语法 v-bind:子组件props中的变量名="父组件中的data数据"

子组件->父组件:通过$emit创建自定义事件发送数据

1
2
3
4
5
步骤1:子创建自定义事件       通过语法  this.$emit(事件名称,数据1,...,数据n)
步骤2:父调用自定义事件获取数据  父必须在调用的子组件上触发事件,语法@自定义事件="函数名"

留心1:函数在父定义
留心2:底层会将自定义事件中的数据 传递给函数的形参

兄弟组件:通过EventBus(事件总线)

1
2
3
4
const eventBus = new Vue()   // 相当于创建一个组件数据共享中心

// 发送数据:eventBus.$emit(自定义事件名称,数据1,.....,数据n)
// 接受数据(监控传递):eventBus.$on(自定义事件名称,处理函数)

组件通信(父-子)

  • 需求
1
2
3
4
5
6
自定义组件fathertag输出:
<div><p>我是父组件,我儿子叫:赵冠希</p>【<p>我是子组件,我爸爸给我取名:赵冠希</p>】</div>
其中子组件sontag部分:【】
变量:sonName-赵冠希

为了更明显看出父子关系推荐:https://www.w3school.com.cn/tags/tag_fieldset.asp
  • 代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bEmYl9sf-1590890282726)(images/1585208094600.png)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <fathertag></fathertag>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("fathertag", {
   
    // 声明父组件中的数据
    data() {
        return {
            sonName: '赵冠希' // 调用的时候注意大小写
        }
    },
    // 声音父组件内容
    template: `
        <fieldset>
            <legend>父组件</legend>
            <p>我是父组件,我儿子叫:{{sonName}}</p>
            <sontag v-bind:myName="sonName"></sontag>
        </fieldset>
    `,
    // 声明普通方法
    methods: {},
    // 声明子组件
    components: {
        // 键 - 子组件标签名,值 - 是对象里面有template、data、methods等
        sontag: {
            // 声明props属性来接受父传递的数据
            props: ["myName"], // 留心:这么写就相当于在子的data中声明了myName模型数据
            // 声明子组件的内容
            template: `
                <fieldset>
                    <legend>子组件</legend>
                    <p>我是子组件,我爸爸给我取名:{{myName}}</p>
                </fieldset>
            `
        }
    }
})

const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>

组件通信(子-父)

  • 需求
1
2
3
4
上述代码基础上,在父组件fn1方法中能够获取子的myName2数据

子创建getSonData事件
父通过showSonData方法获取

  • 代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hoZGu5a3-1590890282728)(images/1585210350052.png)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <fathertag></fathertag>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('fathertag', {
    // 声明父组件的内容
    template: `
        <fieldset>
            <legend>父组件</legend>
            <div>
                <p>我是父组件,我儿子叫:{{mySonData}}</p>
                <sontag @getSonData="showSonDataFn"></sontag>
            </div>
        </fieldset>
    `,
    // 声明父的模型数据
    data() {
        return {
            mySonData: ''
        }
    },
    // 声明父的普通方法
    methods: {
        showSonDataFn(data) { // 这边有形参,几个呢 看自定义事件中传递了几个
            // console.log(data)
            this.mySonData = data
        }
    },
    // 声明子组件
    components: {
        // 键-子组件名称,值-对象 里面有template、methods、data等
        sontag: {
            // 声明子组件的内容
            template: `
                <fieldset>
                    <legend>子组件</legend>
                    <p>我是子组件,我爸爸给我取名:{{myName2}}</p>
                </fieldset>
            `,
            // 声明子组件模型数据
            data() {
                return {
                    myName2: '神龙教主'
                }
            },
            // 需求:子的数据传递给父用,因为父不能直接获取
            // 思考:子声明时候创建自定义事件
            // 回答:1 用户和网页交互后创建, 2 网页加载完毕后创建自定义事件 (咱们目前的方案)
            // 之前:js中window.onload  jq $(function() {})
            // 现在:使用mounted()
            mounted() {
                // 目前简单理解为
                // 网页加载完毕后创建自定义事件
                // 创建自定义事件语法:this.$emit('事件名称', 数据1,...,数据n)

                // this.$emit("getSonData", 1111, 2222)
                this.$emit("getSonData", this.myName2)
            }
        }
    }
})  

const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>

组件通信(兄弟)

  • 需求
1
2
步骤1:分别定义mytag1和mytag2组件,先写fieldset然后写button
步骤2:点击mytag1组件中的按钮,将mytag1组件中的msg变量传递给mytag2使用
  • 代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VqIKMuwW-1590890282731)(images/1585211323689.png)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <mytag1></mytag1>
    <mytag2></mytag2>
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 定义数据共享中心
const eventBus = new Vue()

Vue.component('mytag1', {
    data() {
        return {
            msg: '神龙之父'
        }
    },
    template: `
        <fieldset>
            <legend>兄弟1</legend>
            <button @click="sendDataFn">点击传递msg数据给兄弟2</button>
        </fieldset>
    `,
    methods: {
        sendDataFn() {
            // 发送数据:eventBus.$emit('事件名称', 数据1,...,数据n)
            eventBus.$emit('mytag1MsgData', this.msg)
        }
    }
})

Vue.component('mytag2', {
    template: `
        <fieldset>
            <legend>兄弟2</legend>
            这是我兄弟1传递的数据:【{{broData}}】
        </fieldset>
    `,
    data() {
        return {
            broData: ''
        }
    },
    // 之前:js window.onload jq $(function(){})
    // 现在:vue中
    mounted() {
        // 接受数据(监控传递数据):eventBus.$on('事件名称', 处理函数)
        eventBus.$on('mytag1MsgData', (msg) => {
            // console.log(msg)
            this.broData = msg
        })
    }
})
       
const vm = new Vue({
    el: '#app',
    data: {

    }
})
</script>
</body>
</html>

小总结

首先:大家发现还是挺麻烦的,那你别管那么多只要把握下述语法理解怎么用 然后复制实现即可

其次:主要搞明白父子、子父工作场景还是较为多,因为后面会有一个vuex库来代替

原理:上述语法是我总结的,官方参考手册

1
2
https://cn.vuejs.org/v2/guide/components-props.html
https://cn.vuejs.org/v2/guide/components-custom-events.html

父->子(!

1
2
步骤1:子通过props接受数据
步骤2:父在调用子组件的标签上通过v-bind传递数据即可

子->父(!

1
2
步骤1:子创建自定义事件,通过this.$emit语法
步骤2:父在调用子组件的标签上通过@自定义事件名称="函数名"获取数据

兄弟(!

1
2
3
步骤1:创建数据共享中心 const eventBus = new Vue()
步骤2:通过eventBus.$emit发送数据
步骤3:通过eventBus.$on监控接受数据

五、生命周期&钩子函数(!!!)

明确需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZoeIs7d-1590890282733)(images/1575004739510.png)]

说明:前面做过一个todolist案例数据是固定不变的

需求:数据动态,也就是请求接口。

思考:什么时候发送异步请求? 换句话说在哪写代码(以前:onload和$(function(){})

现在: mounted

语法说明

生命周期:指代码可用和不可用时间(举例:局部变量声明周期,函数调用产生,函数调动完毕销毁)

钩子函数:在指定场景下触发的普通函数

https://cn.vuejs.org/v2/guide/instance.html#生命周期图示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jo36VFk-1590890282734)(images/1575005083760.png)]

代码推进

  • 代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHmrfKbr-1590890282736)(images/1585213703433.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJHTC5rP-1590890282739)(images/1585213750929.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XGt63jNh-1590890282740)(images/1585213860242.png)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    {{msg}}
</div>
<script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const vm = new Vue({
    el: '#app',
    data: {
        msg: "神龙之母"
    },
    beforeCreate() {
        console.group("beforeCreate:HTML没有剪切,模型没有初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    created() {
        console.group("created:HTML没有剪切,模型已经初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    beforeMount() {
        console.group("beforeMount:HTML已经剪切,HTML数据还没替换,模型已经初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    mounted() { // 挂载完毕,监控范围里面有vue语法 已经全部替换成最终数据
        console.group("mounted:模型已经初始化、HTML数据已经替换完毕,并且放到了监控范围中")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },

   
    beforeUpdate() {
        console.group("beforeUpdate")
        console.log('模型数据修改前触发')
        console.groupEnd()
    },
    updated() {
        console.group("updated")
        console.log('模型数据修改后触发')
        console.groupEnd()
    },
    beforeDestroy() {
        console.group("beforeDestroy:组件销毁前")
        console.groupEnd()
    },
    destroyed() {
        console.group("destroyed:组件销毁后")
        console.groupEnd()
    }

})
</script>
</body>
</html>
  • 思考:在beforeCreate和mounted中谁能够输出模型中值?为什么?
1
2
3
4
5
回答:mounted

beforeCreate  监控范围中的HTML未剪切到内存、模型未初始化
mounted  HTML已剪切到内存、HTML挂载/监控范围里面的vue模板语法替换成最终的数据 放到页面中、模型已初始化
         脚下留心:mounted目前说已经挂载了(但:有特殊情况 它并不能保证 后面说 nextTick

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ox0MUIrJ-1590890282743)(images/1585214255283.png)]

小总结

概念

1
2
钩子函数:在指定场景下触发的函数,举例(模型数据修改了才会有beforeUpdate和updated
生命周期:指代码可用和不可用的时间,举例(data模型中的数据 created函数时才可以用

钩子函数:默认的8个

1
2
3
4
5
6
7
8
9
10
beforeCreate   HTML没加载、模型没初始化
created        HTML没加载、模型已初始化
beforeMount    HTML已加载、HTML未解析、模型已初始化、
mounted        HTML已加载、HTML已解析、模型已初始化  (真的所有组件都放到页面中了吗 !!nextTick)

beforeUpdate
updated

beforeDestroy
destroyed

现在你对vue生命周期了解了吗,有哪些呢

1
2
3
4
常用有8个,分别是创建、挂载、更新、卸载各两个,我再某某项目中,常用的就是created和mounted

什么时候触发updated相关的:模型数据变化
什么时候触发destroyed相关的:vm.$destroy()

思考:发送异步请求在哪里是用?

回答:created 会比mounted稍微快一丢丢 只要模型初始化好了就可以发送异步请求

回头看看

混入(mixin)

1
2
3
4
5
6
7
混入(mixin):是vue提供的一个技术,顾名思义将代码混合到一起(提取)从而减少代码冗余,提高代码复用
语法
Vue.mixin({
    data() { return {} },
    methods
    ...
})

组件

1
2
3
4
5
6
7
8
9
10
11
12
什么是组件(作用):就是一个文件,存放HTML、CSS、JS
组件的好处:减少代码冗余、便于后期维护
创建组件语法:
Vue.component(标签名, { //留心:标签名后期调用如果有大写,改为【-小写】 因为html不识别大小写
    template:``        // 声明组件内容
    data() { return {} },
    methods: {},
    components: {}     //声明子组件 键就是子组件标签名,值是对象里面写template等
})

组件中如何渲染数据:{{data中的键}}
组件中如何调用事件:@click="函数名"

动态组件

1
2
概念:多个组件,动态展示
语法:<component is="组件名/标签名/标识"></component>

组件通信/传值!!!

父->子(很重要

1
2
步骤1:子通过props接受数据
步骤2:父在调用子组件的标签上通过v-bind传递数据即可

子->父(很重要

1
2
步骤1:子创建自定义事件,通过this.$emit语法
步骤2:父在调用子组件的标签上通过@自定义事件名称="函数名"获取数据

兄弟(很重要

1
2
3
步骤1:创建数据共享中心 const eventBus = new Vue()
步骤2:通过eventBus.$emit发送数据
步骤3:通过eventBus.$on监控接受数据

生命周期&钩子函数!!!

概念

1
2
钩子函数:在指定场景下触发的函数,举例(模型数据修改了才会有beforeUpdate和updated
生命周期:指代码可用和不可用的时间,举例(data模型中的数据 created函数时才可以用

钩子函数:默认的8个

1
2
3
4
5
6
7
8
9
10
beforeCreate   HTML没加载、模型没初始化
created        HTML没加载、模型已初始化
beforeMount    HTML已加载、HTML未解析、模型已初始化、
mounted        HTML已加载、HTML已解析、模型已初始化  (真的所有组件都放到页面中了吗 !!nextTick)

beforeUpdate
updated

beforeDestroy
destroyed