[Vue psutil模块、echars的使用、与后端交互的三种方式、计算属性、Mixins、dom和diff算法、全局组件、局部组件、父传子、子传父、ref属性、事件总线]

[Vue psutil模块、echars的使用、与后端交互的三种方式、计算属性、Mixins、dom和diff算法、全局组件、局部组件、父传子、子传父、ref属性、事件总线]

psutil模块

简介


psutil是一个跨平台库(http://pythonhosted.org/psutil/)能够轻松实现获取系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息.

它主要用来做系统监控,性能分析,进程管理。

它实现了同等命令行工具提供的功能,如ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等。目前支持32位和64位的Linux、Windows、OS X、FreeBSD和Sun Solaris等操作系统.

安装psutil模块


pip3 install psutil

获取系统基本信息的使用

CPU信息

cpu_times() 获取CPU完整信息


print(psutil.cpu_times())

# scputimes(user=89295.53125, system=77180.578125, idle=649627.59375, interrupt=4747.625, dpc=2285.203125)

获取单个数据,如用户的cpu时


print(psutil.cpu_times().user)

# 89388.45312499999

cpu_count() 获取cpu逻辑和物理个数,默认logical值为True


#CPU逻辑个数

    print(psutil.cpu_count())
    # 4
#CPU物理个数

    print(psutil.cpu_count(logical=False))
    # 2

cpu_percent() 获取cpu的使用率


print(psutil.cpu_percent(1,percpu=True))
# [20.0, 18.5, 12.3, 13.8]
print(psutil.cpu_percent(percpu=True))
# [0.0, 0.0, 0.0, 0.0]

print(psutil.cpu_percent(1))
# 33.7
print(psutil.cpu_percent(percpu=True))
# [36.4, 29.2, 35.4, 33.8]

内存信息

virtual_memory() 获取内存信息,swap使用就用swap_memory()方法


print(psutil.virtual_memory())
# svmem(total=8425320448, available=2924511232, percent=65.3, used=5500809216, free=2924511232)

print(psutil.swap_memory())
# sswap(total=14599335936, used=7110447104, free=7488888832, percent=48.7, sin=0, sout=0)

percent表示实际已经使用的内存占比,即(1047543808-717537280)/1047543808*100% 。

available表示还可以使用的内存。

磁盘信息

磁盘信息主要有两部分,一个是磁盘的利用率,一个是io,他们分别可以通过disk_usage和disk_io_counters方法获取。

如下先获取分区信息,然后看下根分区的使用情况:


print(psutil.disk_partitions())
# [sdiskpart(device='C:\\', mountpoint='C:\\', fstype='NTFS', opts='rw,fixed', maxfile=255, maxpath=260), sdiskpart(device='D:\\', mountpoint='D:\\', fstype='NTFS', opts='rw,fixed', maxfile=255, maxpath=260)]

print(psutil.disk_usage('/'))
# sdiskusage(total=170147328000, used=75902009344, free=94245318656, percent=44.6)

默认disk_io_counters方法获取的是硬盘总的io数和读写信息,如果需要获取单个分区的io和读写信息加上"perdisk=True"参数。


print(psutil.disk_io_counters())
# sdiskio(read_count=1843048, write_count=2572395, read_bytes=58439621120, write_bytes=95755351040, read_time=1508, write_time=1301)

print(psutil.disk_io_counters(perdisk=True))
# {'PhysicalDrive0': sdiskio(read_count=1843051, write_count=2572627, read_bytes=58439633408, write_bytes=95769238528, read_time=1508, write_time=1301)}

网络信息

网络io和磁盘io使用方法差不多,主要使用net_io_counters方法,如果需要获取单个网卡的io信息,加上pernic=True参数。


#获取网络总的io情况

print(psutil.net_io_counters())
# snetio(bytes_sent=4323296995, bytes_recv=85900285374, packets_sent=20948831, packets_recv=744999, errin=0, errout=0, dropin=0, dropout=0)

#获取网卡的io情况

print(psutil.net_io_counters(pernic=True))
# {'WLAN': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), '本地连接* 1': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), '本地连接* 2': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), '以太网': snetio(bytes_sent=4323296251, bytes_recv=85900304865, packets_sent=20947000, packets_recv=745126, errin=0, errout=0, dropin=0, dropout=0), 'VMware Network Adapter VMnet1': snetio(bytes_sent=588, bytes_recv=8, packets_sent=588, packets_recv=8, errin=0, errout=0, dropin=0, dropout=0), 'VMware Network Adapter VMnet8': snetio(bytes_sent=1275, bytes_recv=8, packets_sent=1275, packets_recv=8, errin=0, errout=0, dropin=0, dropout=0), 'Loopback Pseudo-Interface 1': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0)}


其他系统信息

获取开机时间


# 以linux时间格式返回,可以使用时间戳转换

    print(psutil.boot_time())
    # 1625977244.9221938

# 转换成自然时间格式

    print(datetime.datetime.fromtimestamp(psutil.boot_time ()).strftime("%Y-%m-%d %H: %M: %S"))
    # 2021-07-11 12: 20: 44

查看系统全部进程


print(psutil.pids())

# [0, 4, 100, 108, 120, 392, 532, 604, 720, 792, 812, 892, 928, 956, 1016, 1056, 1120, 1168, 1236, 1268, 1296, 1412, 1448, 1576, 1604, 1632, 1724, 1736, 1764, 1788, 1800, 1848, 1884, 1908, 1972, 2024, 2036, 2044, 2076, 2100, 2172, 2236, 2240, 2268, 2316, 2328, 2428, 2468, 2508, 2560, 2588, 2592, 2604, 2620, 2628, 2716, 2828, 2836, 2956, 2980, 2992, 3024, 3088, 3156, 3180, 3192, 3200, 3204, 3216, 3240, 3320, 3396, 3404, 3452, 3468, 3548, 3624, 3672, 3832, 3840, 3852, 3860, 3872, 3880, 3896, 3920, 3972, 4004, 4024, 4032, 4052, 4104, 4112, 4272, 4560, 4608, 4616, 4792, 4900, 4924, 5232, 5368, 5628, 5648, 5700, 6088, 6096, 6148, 6236, 6308, 6312, 6336, 6644, 6772, 6928, 7296, 7340, 7364, 7376, 7632, 7732, 7984, 7996, 8020, 8044, 8384, 8720, 8764, 8912, 9008, 9068, 9152, 9272, 9344, 9384, 9444, 9504, 9512, 9520, 9708, 9716, 9880, 10012, 10432, 10480, 10640, 10712, 10816, 10980, 11024, 11088, 11484, 11496, 11512, 11580, 11604, 11684, 11720, 11880, 11912, 11936, 12100, 12272, 12280, 12736, 13108, 13280, 13436, 13480, 13488, 13548, 13556, 13632, 13652, 13728, 13836, 14188, 14396, 14412, 14468, 14480, 14740, 15000, 15032]

查看单个进程


p = psutil.Process(16031)
p.name()      	   #进程名
p.exe()            #进程的bin路径
p.cwd()			   #进程的工作目录绝对路径
p.status()		   #进程状态
p.create_time()	   #进程创建时间
p.uids()		   #进程uid信息
p.gids()		   #进程的gid信息
p.cpu_times()      #进程的cpu时间信息,包括user,system两个cpu信息
p.cpu_affinity()   #get进程cpu亲和度,如果要设置cpu亲和度,将cpu号作为参考就好
p.memory_percent() #进程内存利用率
p.memory_info()    #进程内存rss,vms信息
p.io_counters()    #进程的IO信息,包括读写IO数字及参数
p.connectios()     #返回进程列表
p.num_threads()    #进程开启的线程数

听过psutil的Popen方法启动应用程序,可以跟踪程序的相关信息

from subprocess import PIPE
p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"],stdout=PIPE)
p.name()
p.username()


查看系统硬件脚本


#!/usr/bin/env python
 #coding:utf-8
 
 import psutil
 import datetime
 import time
 
 # 当前时间
 now_time = time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime(time.time()))
 print(now_time)
 
 # 查看cpu物理个数的信息
 print(u"物理CPU个数: %s" % psutil.cpu_count(logical=False))
 
 #CPU的使用率
 cpu = (str(psutil.cpu_percent(1))) + '%'
 print(u"cup使用率: %s" % cpu)
 
 #查看内存信息,剩余内存.free  总共.total
 #round()函数方法为返回浮点数x的四舍五入值。
 
 free = str(round(psutil.virtual_memory().free / (1024.0 * 1024.0 * 1024.0), 2))
 total = str(round(psutil.virtual_memory().total / (1024.0 * 1024.0 * 1024.0), 2))
 memory = int(psutil.virtual_memory().total - psutil.virtual_memory().free) / float(psutil.virtual_memory().total)
 print(u"物理内存: %s G" % total)
 print(u"剩余物理内存: %s G" % free)
 print(u"物理内存使用率: %s %%" % int(memory * 100))
 # 系统启动时间
 print(u"系统启动时间: %s" % datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S"))
 
 # 系统用户
 users_count = len(psutil.users())
 #
 # >>> for u in psutil.users():
 # ...   print(u)
 # ...
 # suser(name='root', terminal='pts/0', host='61.135.18.162', started=1505483904.0)
 # suser(name='root', terminal='pts/5', host='61.135.18.162', started=1505469056.0)
 # >>> u.name
 # 'root'
 # >>> u.terminal
 # 'pts/5'
 # >>> u.host
 # '61.135.18.162'
 # >>> u.started
 # 1505469056.0
 # >>>
 
 users_list = ",".join([u.name for u in psutil.users()])
 print(u"当前有%s个用户,分别是 %s" % (users_count, users_list))
 
 #网卡,可以得到网卡属性,连接数,当前流量等信息
 net = psutil.net_io_counters()
 bytes_sent = '{0:.2f} Mb'.format(net.bytes_recv / 1024 / 1024)
 bytes_rcvd = '{0:.2f} Mb'.format(net.bytes_sent / 1024 / 1024)
 print(u"网卡接收流量 %s 网卡发送流量 %s" % (bytes_rcvd, bytes_sent))
 
 io = psutil.disk_partitions()
 # print(io)
 # print("io[-1]为",io[-1])
 #del io[-1]
 
 print('-----------------------------磁盘信息---------------------------------------')
 
 print("系统磁盘信息:" + str(io))
 
 for i in io:
     o = psutil.disk_usage(i.device)
     print("总容量:" + str(int(o.total / (1024.0 * 1024.0 * 1024.0))) + "G")
     print("已用容量:" + str(int(o.used / (1024.0 * 1024.0 * 1024.0))) + "G")
     print("可用容量:" + str(int(o.free / (1024.0 * 1024.0 * 1024.0))) + "G")
 
 print('-----------------------------进程信息-------------------------------------')
 # 查看系统全部进程
 for pnum in psutil.pids():
     p = psutil.Process(pnum)
     print(u"进程名 %-20s  内存利用率 %-18s 进程状态 %-10s 创建时间 %-10s " \
     % (p.name(), p.memory_percent(), p.status(), p.create_time()))

echars的使用

详情点击官网查看

导入cdn或者文件

# cnd
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js"></script>

# 或者文件
<script src="./js/echarts.min.js"></script>

使用


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/sweetalert/1.1.3/sweetalert.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./js/vue.js"></script>
    <script src="./js/echarts.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js"></script>

</head>
<body>

<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 100%;height:400px;"></div>

<script type="text/javascript">
    // 基于准备好的dom,初始化echarts实例
    var myChart = echarts.init(document.getElementById('main'));

    // 指定图表的配置项和数据
    var option = {
        title: {
            text: 'ECharts 展示'
        },
        tooltip: {},
        legend: {
            data: ['智商']
        },
        xAxis: {
            data: ["刘鹏飞", "刘鹏飞啊飞", "老胡", "火神", "老郑", "左大",'颜值担当','刘浩杰']
        },
        yAxis: {},
        series: [{
            name: '销量',
            type: 'bar',
            data: [112, 105, 110, 100, 102, 103,130,125]
        }]
    };

    // 使用刚指定的配置项和数据显示图表。
    myChart.setOption(option);
</script>

</body>
</html>

与后端交互的几种方式

jquery的ajax(不推荐使用)

fetch(不是所有浏览器都支持,谷歌浏览器支持)

axios(基本都是用它)

jquery-ajax 与后端交互

前端

<div id="test">

    <button @click="onefunc">按钮一个</button>

</div>

<script>
    var vm = new Vue({
        el: '#test',
        data: {
            shuju: 'asdf',
        },
        methods: {
            onefunc() {
                $.ajax({
                    url: 'http://127.0.0.1:5000/',
                    type: 'get',
                    dataType: 'json',# 不写这个后端返回的json格式不会自动反序列化,也就是字符串
                    success: args => {
                        console.log(args)
                        console.log(typeof args)
                        let args = JSON.parse(args) # 也可以前端手动反序列化 
                    }
                })
            }
        }
    })
</script>

后端
from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
    with open('./data.json','r',encoding='utf-8') as f:
        res=f.read()
    # res = {
    #     "liupengfei": {"name": "liupengfei", "age": 20},
    #     "liuhaojie": {"name": "liuhaojie", "age": 21},
    #     "laohu": {"name": "laohu", "age": 22},
    # }

    # 响应头中加入key-value:Access-Control-Allow-Origin
    # 允许跨域,任意的前端都可以向我发送请求
    resp = make_response(res)
    resp.headers['Access-Control-Allow-Origin'] = '*'
    return resp


if __name__ == '__main__':
    app.run()

fetch:(原生的)与后端交互

<script>
    var vm = new Vue({
        el: '#test',
        data: {
            shuju: 'asdf',
        },
        methods: {
            onefunc() {
                fetch('http://127.0.0.1:5000/').then(res => res.json()).then(res => {
                    console.log(typeof res)
                    console.log(res)
                })
            }
        }
    })

</script>


如果没有.then(res => res.json())返回的是个Response

axios与后端交互(用的最多)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    
    # 需要导入cdn 或者下载到本地导入
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>

<div id="app">
    <div v-for="data in data_list">
        <h3>{{data.name}}</h3>
        <img :src="data.poster" alt="">
        <h5>导演:{{data.director}}</h5>
    </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            data_list: []
        },
        methods: {
            get_data() {
                //发送请求
                // axios.get('http://127.0.0.1:5000/').then(res => {
                //     // res.data才是真正后端返回的响应体中的内容
                //         console.log(res.status)
                //     this.data_list = res.data.data.films
                //
                // })
                axios({
                    url: 'http://127.0.0.1:5000/',
                    methods: 'get',

                }).then(res => {
                    // res.data才是真正后端返回的响应体中的内容
                    console.log(res.status)
                    this.data_list = res.data.data.films

                })

            }
        },
        mounted() {
            this.get_data()
        },
    })
</script>
</html>

计算属性

计算属性的特点:只要返回的结果没有发生变化,那么计算属性就只会被执行一次

计算属性的应用场景:由于计算属性会将返回的结果缓存起来,所以如果返回的数据不经常发生变化
那么使用计算属性的性能就会比使用函数的性能高


计算属性优点  computed :{}

    1、在同一个页面中使用多次计算属性,不会多次执行
    
    2、不需要加括号,直接使用


<div id="app01">
    
    <p>自动运行的方法 {{funcone()}} </p>
    <p>自动运行的方法 {{funcone()}} </p>
    <p>自动运行的属性 {{functwo}} </p>
    <p>自动运行的属性 {{functwo}} </p>

</div>
<script>
    var vm = new Vue({
        el: '#app01',
        data: {
            func: '方法',
            shuxing: '属性',
        },
        methods: {
            funcone() {
                console.log('执行了方法,打印:', this.func)
            }
        },
        computed: {
            functwo() {
                console.log('执行了计算属性,打印:', this.shuxing)
                return this.shuxing
            }
        }
    })
</script>

只要有变动,方法就都会每个执行一遍,而计算属性,只会执行一次方法。

计算属性几个问题

页面渲染问题


页面当开始渲染的时候,应该是先找data里面的属性,然后找 computed 计算属性,最后找methods,找不到嗝屁。

事件触发问题


<p @click="funcone">点我</p>
    
	funcone 会去找方法,如果只写计算属性方法,只会刷新页面的时候执行一次计算属性里面的方法,后面点击也不会执行计算属性方法,方法 funcone 作为属性的时候只能找 methods 里面的方法。

<p @click="funcone()">点我</p>

	这种情况下,如果只写了计算机属性方法,执行完计算机属性方法之后,会一直报错。
    
当然,如果写了方法,事件触发的对应函数带不带括号无关紧要。

插值语法放方法

只写了方法:

    <p>自动运行的方法 {{funcone()}} </p>

        页面 :自动运行的方法

    <p>自动运行的方法 {{funcone}} </p>

        页面显示 :自动运行的方法 function () { [native code] }

只写了计算属性:

    <p>自动运行的方法 {{funcone}} </p>
    <p>自动运行的方法 {{funcone()}} </p>
    
    页面 : 空白
        
插值语法放入方法,带上括号直接刷新页面的时候就已经执行,会去方法里面找,在这之前会经过计算属性,然后触发计算属性的方法, 再报错 ,因为找不到methods里面的方法。

关于方法和计算属性需要注意的一个点


不要 funcone 计算属性里面的方法和 methods 里面的方法一样。

# 因为会报错

Mixins


混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。

混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

虚拟dom和diff算法

Vue2.0 v-for 中 :key 有什么用呢?


其实呢不只是vue,react中在执行列表渲染时也会要求给每个组件添加key这个属性。
key简单点来说就是唯一标识,就像ID一样唯一性
要知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。


只做同层级的对比
按照key值比较,出现新的key就插入
通组件对比

虚拟DOM的diff算法

参考 :https://segmentfault.com/a/1190000020170310

组件介绍,全局组件,局部组件

组件的作用


扩展 HTML 元素,封装可重用的代码,目的是复用
	-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
	-组件把js,css,html放到一起,有逻辑,有样式,有html
    
组件分类:局部组件和全局组件

组件注册方式


1、全局组件

	Vue.component('myall', {
   
})
    
2、局部组件

	Vue.component('myheader', {
        components:{
                child:{}
    }
})

全局组件


<div id="app01">

    <mydiv></mydiv>

</div>
<script>
    
    # 没有代码提示,语法检查,目前这么用
    # 后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包

    # 定义一个全局组件
    # 组件可以有data,methods,computed....,但是data 必须是一个函数,其他和原来Vue使用一样
    
    Vue.component('mydiv', {
        template: `
        <div>
            <h1 style="font-size: 80px;background-color: deepskyblue">我是全局组件</h1>
            <button @click="func">这是一个弹出按钮</button>
        </div>
        `,
        data() {
            return {
                name: '颜值担当'
            }
        },
        methods: {
            func() {
                alert('弹出了一个框')
            }
        }
    })
    var vm = new Vue({
        el: '#app01',
        data: {
            func: '方法',
            shuxing: '属性',
        },
    })
</script>

局部组件


<div id="app01">
    
    <mydiv></mydiv>

</div>
<script>
    Vue.component('mydiv', {
        # 如果有局部组件全局组件使用,需要在template注册局部组件标签。
        template: `
        <div>
            <h1 style="font-size: 80px;background-color: deepskyblue">我是全局组件</h1>
            <button @click="func">这是局部组件召唤按钮</button>
            <child v-show="isshowa"></child>
        </div>
        `,
        data() {
            return {
                name: '颜值担当',
                isshowa:false
            }
        },
        methods: {
            func() {
                this.isshowa = !this.isshowa
            }
        },
        components: {
            child: {
                template: `
                         <div>
                         <p>我只是个简简单单的{{name}}罢了</p>
                         <p>我只是个简简单单的{{name}}罢了</p>
                         </div>
                        `,
                data() {
                    return {name: '局部组件'}
                }
            }
        }
    })
    var vm = new Vue({
        el: '#app01',
        data: {
            func: '方法',
            shuxing: '属性',
        },
    })
</script>

组件通信


1、父子组件传值 (props down, events up)

2、父传子之属性验证props:{name:Number}Number,String,Boolean,Array,Object,Function,null(不限制类型)
    
3、事件机制a.使用 $on(eventName) 监听事件b.使用 $emit(eventName) 触发事件

4、Ref<input ref="mytext"/>  this.$refs.mytext

5、事件总线var bus = new Vue();* mounted生命周期中进行监听

组件通信之父传子(通过自定义属性的方式)


父中:<myheader :myname="name" :myshow="false"></myheader>
子中:props:['myname','myshow']
# 子中:props:{myname:类型,myshow:类型]}

示例


<div id="app">

    <myheader :Vm_name="liuhaojie"></myheader>

</div>
</body>
<script>

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{Vm_name}}</h1>
        </div>
        `,
        props:['Vm_name',]
        // 属性验证
        // props:{
        //     myname:String,
        //     myshow:Boolean
        // }
    })
    var vm = new Vue({
        el: '#app',
        data: {
            liuhaojie:'颜值担当'
        },
    })

</script>

示例


<div id="app">

    <myheader :Vm_name="liuhaojie"></myheader>

</div>
</body>
<script>

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{Vm_name}}</h1>
                <erzi :inner="Vm_name"></erzi>
        </div>
        `,
        props: ['Vm_name',],

        components: {
            erzi: {
                template: `
                    <div>
                        <span>这是局部的{{ inner }}</span>
                    </div>
                `,
                props: ['inner',],
            }
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {
            liuhaojie: '颜值担当'
        },
    })

</script>

属性验证


对传过来的属性进行类型的验证,验证不成功会抛异常报错,但是一般情况下还是可以渲染出来。

<div id="app">

    <myheader :Vm_name="liuhaojie"></myheader>

</div>
</body>
<script>

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{Vm_name}}</h1>
                <erzi :inner="Vm_name"></erzi>
        </div>
        `,
        props: ['Vm_name',],

        components: {
            erzi: {
                template: `
                    <div>
                        <span>这是局部的{{ inner }}</span>
                    </div>
                `,
                // props: ['inner',],
                props:{
                    inner:String
                }
            }
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {
            liuhaojie: 1
        },
    })

组件通信之子传父(通过自定义事件)

示例


<div id="test">

    <myall @onefunc="funcone"></myall>

</div>
<script>

    Vue.component('myall', {
        template: `
        <div>
            <p>{{innerdata}}</p>
            <button @click="buttonfunc">这是一个按钮啊</button>
        </div>
        `,
        data(){
            return {innerdata:'这是全局的组件'}
        },
        methods: {
            buttonfunc(){
                // 触发父组件中onefunc这个自定义事件对应的函数执行
                this.$emit('onefunc',this.innerdata)
            }
        }
    })

    var vm = new Vue({
        el: '#test',
        methods:{
            funcone(args){
                console.log(args)
            }
        }

    })
</script>


ref属性


ref放在标签上,拿到的是原生节点

ref放在组件上,拿到的是组件对象

    通过这种方式实现子传父(this.$refs.mychild.text)
    通过这种方式实现父传子(调用子组件方法传参数)

示例


------------------------------------ ref 属性展示 -------------------------------------

<div id="test">

    <span ref="gen">这是根组件</span>
    <myall ref="all"></myall>
    <button @click="functwo">按钮</button>

</div>
<script>

    Vue.component('myall', {
        template: `
        <div>
            <p>{{innerdata}}</p>
        </div>
        `,
        data(){
            return {innerdata:'这是全局的组件'}
        },
    })

    var vm = new Vue({
        el: '#test',
        methods:{
            functwo(){
                console.log(this.$refs)
            }
        }

    })
</script>

示例


------ ref 也可以拿到组件对象的属性和方法 ----------------------------------------------

<div id="test">

    <myall ref="all"></myall>
    <button @click="functwo">按钮</button>
    <span ref="gen">这是根组件拿到的全局组件数据:{{vmdata}}</span>

</div>
<script>

    Vue.component('myall', {
        template: `
        <div>
            <p>局部组件打印:{{innerdata}}</p>
        </div>
        `,
        data() {
            return {innerdata: '这是全局的组件的数据',}
        },
        methods:{
            innerfunc(){
                return this.innerdata
            }
        }
    })

    var vm = new Vue({
        el: '#test',
        data: {
            vmdata: ''
        },
        methods: {
            functwo() {
                this.vmdata = this.$refs.all.innerfunc()
            }
        }

    })
</script>

事件总线(不同层级的不同组件通信)


注意事项!!!

	1、需要再 new 一个 Vue 对象 作为中央事件总线
	2、bus.$emit()写在methods方法里面,但是 bus.$on()一定要写在 mounted()
	3、根Vue需要放在组件最下面,否则异常
            

<div id="test">

    <myallone></myallone>
    <myalltwo></myalltwo>

</div>
<script>

    // 借助事件总线,实现跨组件通信
    // 定义一个事件总线
    var bus = new Vue()

    Vue.component('myallone', {
        template: `
        <div>
            <p>全局组件one打印:{{innerdata}}</p>
            <button @click="innerfuncone"> 全局组件one给two发信息 </button>
        </div>
        `,
        data() {
            return {innerdata: '这是全局的组件 1 的数据', msg1: '我是组件1啊'}
        },
        methods: {
            innerfuncone() {
                bus.$emit('ceshi', this.msg1)
            }
        }

    })

    Vue.component('myalltwo', {
        template: `
        <div>
            <p>全局组件two打印:{{innerdata}}</p>
            <p>全局组件two收到one的信息:{{msg2}}</p>
        </div>
        `,
        data() {
            return {innerdata: '这是全局的组件 2 的数据', msg2: ''}
        },

        mounted() {
            bus.$on('ceshi', msg1 => {
                this.msg2 = msg1
            })
        }
    })
	
    # 一定要放在最下面
    var vm = new Vue({
        el: '#test',
        data: {
            vmdata: ''
        },
        methods: {}
    })

</script>

posted @ 2021-07-18 14:33  刘较瘦丫  阅读(345)  评论(0)    收藏  举报