• Vue组件


    组件

    1 fetch和axios

    axios与fetch实现数据请求

    (1)fetch(不是所有浏览器都支持,谷歌浏览器支持)
    XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好。 兼容性不好
    polyfill: https://github.com/camsong/fetch-ie8

    1.1 fetche使用

    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
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>fetch</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">

    <button @click="handleClick()">获取影片信息</button>
    <ul>
    <li v-for="data in datalist">
    <h3>{{data.name}}</h3>
    <img :src="data.poster"/>
    </li>
    </ul>
    </div>
    <script type="text/javascript">
    new Vue({
    el: "#box",
    data: {
    datalist: []
    },
    methods: {
    handleClick() {
    //https://m.maizuo.com/v5/?co=mzmovie#/films/nowPlaying
    fetch("./json/test.json").then(res => res.json()).then(res => {
    console.log(res.data.films)
    this.datalist = res.data.films
    })
    }
    }
    })

    /*
    // post-1
    fetch("**",{
    method:'post',
    headers: {
    "Content‐Type": "application/x‐www‐form‐urlencoded"
    },
    body: "name=kerwin&age=100",
    credentials:"include"
    }).then(res=>res.json()).then(res=>{console.log(res)});

    // post-2
    fetch("**",{
    method:'post',
    headers: {
    "Content‐Type": "application/json"
    },
    body: JSON.stringify({
    myname:"kerwin",
    myage:100
    })
    }).then(res=>res.json()).then(res=>{console.log(res)});
    */

    </script>
    </body>
    </html>

    1.2 axios的使用

    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
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>axios</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    </head>
    <body>
    <div id="box">
    <button @click="handleClick()">正在热映</button>

    <ul>
    <li v-for="data in datalist">
    <h3>{{data.name}}</h3>
    <img :src="data.poster"/>
    </li>
    </ul>
    </div>
    <script type="text/javascript">

    new Vue({
    el:"#box",
    data:{
    datalist:[]
    },
    methods:{
    handleClick(){
    axios.get("./json/test.json").then(res=>{
    console.log(res.data.data.films) // axios 自动包装data属性 res.data
    this.datalist = res.data.data.films
    }).catch(err=>{
    console.log(err);
    })
    }
    }
    })
    </script>
    </body>
    </html>

    2 计算属性

    1
    2
    3
    4
    5
    复杂逻辑,模板难以维护
    (1) 基础例子
    (2) 计算缓存 VS methods-计算属性是基于它们的依赖进行缓存的。-计算属性只有在它的相关依赖发生改变时才会重新求值
    (3) 计算属性 VS watch
    - v-model3

    2.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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <!--大段的代码写在这里不好,使用计算属性-->
    {{mytext.substring(0,1).toUpperCase()+mytext.substring(1)}}
    <p>计算属性:{{getname}}</p>
    <!--普通方法要加括号-->
    <p>普通方法:{{getNameMethod()}}</p>
    <!--区别是在同一个页面中使用多次计算属性,不会多次执行-->
    </div>
    </body>
    <script>
    var vm = new Vue({
    el: '#box',
    data: {
    mytext:'lqz',
    },
    computed:{
    getname(){//依赖的状态改变了,会重新计算
    console.log('计算属性')
    return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)
    }
    },
    methods:{
    getNameMethod(){
    console.log('普通方法')
    return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)
    }
    }
    })
    </script>
    </html>

    2.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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <p><input type="text" v-model="mytext" @input="handleChange"></p>
    <ul>
    <li v-for="data in newlist">{{data}}</li>
    </ul>
    </div>
    </body>
    <script>
    var vm = new Vue({
    el: '#box',
    data: {
    mytext: '',
    datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],

    },
    computed: {
    newlist() {
    var newlist = this.datalist.filter(item => {
    return item.indexOf(this.mytext) > -1
    })
    return newlist
    },
    },

    })
    </script>
    </html>

    3 Mixins

    1
    混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

    4 虚拟dom与diff算法 key的作用

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

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


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

    4.2 虚拟DOM的diff算法

    image-20201214225437290

    4.3 具体实现

    4.3.1 把树按照层级分解

    image-20201214225736585

    4.3.2 同key值比较

    image-20201214225827633

    4.3.3 通组件对比

    image-20201214225913886

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <div id="box">
    <div v-if="isShow">111</div>
    <p v-else>222</p>
    <!--
    {tag:div,value:111}
    {tag:p,value:222}
    直接不比较,直接删除div,新增p
    -->

    <div v-if="isShow">111</div>
    <div v-else>222</div>
    <!--
    {tag:div,value:111}
    {tag:div,value:222}
    比较都是div,只替换文本内容
    -->
    </div>

    https://segmentfault.com/a/1190000020170310

    5 组件化开发基础

    5.1 组件是什么?有什么用

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

    6 组件注册方式

    1
    2
    3
    1 全局组件
    Vue.component
    2 局部组件

    6.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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <navbar></navbar>
    </div>
    </body>
    <script>
    //没有代码提示,语法检查,目前这么用
    //后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包
    Vue.component('navbar',{
    template:`
    <div>
    <button @click="handleClick">返回</button>
    我是NavBar
    <button style="background: red">主页</button>
    </div>
    `,
    methods:{
    handleClick(){
    console.log('nav nav')
    }
    }
    })
    var vm = new Vue({
    el: '#box',
    data: {
    },

    })
    </script>
    </html>

    6.2 定义局部组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Vue.component('navbar', {
    template: `
    <div>
    <button @click="handleClick">返回</button>
    我是NavBar
    <button style="background: red">主页</button>
    <br>
    <child></child>
    </div>
    `,
    methods: {
    handleClick() {
    console.log('nav nav')
    },
    },
    components: {
    child: {
    template: `<button>儿子</button>`,
    }

    }
    })

    7 组件编写方式与Vue实例的区别

    1
    2
    3
    1 自定义组件需要有一个root element,一般包裹在一个div中
    2 父子组件的data是无法共享
    3 组件可以有data,methods,computed....,但是data 必须是一个函数
    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
    Vue.component('navbar', {
    template: `
    <div>
    <button @click="handleClick">返回</button>
    我是NavBar{{aa}}
    <button style="background: red">主页</button>
    <br>
    <child></child>
    </div>
    `,
    methods: {
    handleClick() {
    console.log('nav nav')
    },
    },
    components: {
    child: {
    template: `<button>儿子</button>`,
    }

    },
    data(){
    return {
    aa:'lqz'
    }
    },
    })

    8 组件通信

    1
    2
    3
    4
    5
    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生命周期中进行监听

    8.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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <!--保证属性名和props中的属性名和变量名一致即可-->
    <navbar myname="lqz"></navbar>
    <navbar myname="egon"></navbar>
    <!--注意数据绑定-->
    <navbar :myname="egon"></navbar>
    <!--可以传多个,但是注意,传入的isshow是字符串,可以使用数据绑定变成布尔-->
    <navbar :myname="egon" isshow="false"></navbar>
    <navbar :myname="egon" :isshow="false"></navbar>
    </div>
    </body>
    <script>
    //没有代码提示,语法检查,目前这么用
    //后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包
    Vue.component('navbar', {
    template: `
    <div>
    <button>返回</button>
    父组件传递的内容是:{{myname}}
    <button>主页</button>
    <br>
    </div>
    `,
    props:['myname']
    })
    var vm = new Vue({
    el: '#box',
    data: {},

    })
    </script>
    </html>

    属性验证

    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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <navbar myname="egon" :isshow="false"></navbar>
    <!--报错-->
    <navbar myname="egon" isshow="false"></navbar>
    </div>
    </body>
    <script>
    Vue.component('navbar', {
    template: `
    <div>
    <button>返回</button>
    父组件传递的内容是:{{myname}}
    传入的布尔是{{isshow}}
    <button>主页</button>
    <br>
    </div>
    `,
    // props:['myname'],
    props:{
    myname:String,
    isshow:Boolean,
    },
    })
    var vm = new Vue({
    el: '#box',
    data: {},

    })
    </script>
    </html>

    8.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
    49
    50
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    子组件中监听自定义事件,随便起名
    <!-- <navbar @myevent="handleClick"></navbar>-->
    <navbar @myevent="handleClick($event)"></navbar>
    </div>
    </body>
    <script>
    Vue.component('navbar', {
    template: `
    <div>
    <button>返回</button>
    组件
    <button @click="handleEvent">点击按钮把子组件数据传递到父组件</button>
    <br>
    </div>
    `,
    data(){
    return {
    name:'lqz'
    }
    },
    methods:{
    handleEvent(){
    // this.$emit('myevent') //myevent:子组件中监听自定义事件
    this.$emit('myevent',100) //100表示传递的参数
    }
    }
    })
    var vm = new Vue({
    el: '#box',
    data: {},
    methods:{
    handleClick(ev){
    console.log('点击子组件,我会执行')
    console.log(ev)

    }
    }

    })
    </script>
    </html>

    8.3 通过子传父控制字组件显示隐藏

    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>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    普通方式
    <button @click="isShow=!isShow">点击隐藏显示</button>
    <navbar v-show="isShow"></navbar>

    <hr>
    字传父方式
    <mybutton @myevent="handleShow"></mybutton>
    <navbar v-show="isShow"></navbar>
    </div>
    </body>
    <script>
    Vue.component('mybutton', {
    template: `
    <div>
    <button @click="handleClick">点我隐藏显示</button>
    </div>
    `,
    methods: {
    handleClick() {
    this.$emit('myevent')
    }
    }
    })

    Vue.component('navbar', {
    template: `
    <div>
    <ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    </ul>
    </div>
    `,
    data() {
    return {
    name: 'lqz'
    }
    },
    methods: {
    handleEvent() {
    // this.$emit('myevent') //myevent:子组件中监听自定义事件
    this.$emit('myevent', 100) //100表示传递的参数
    }
    }
    })
    var vm = new Vue({
    el: '#box',
    data: {
    isShow: true
    },
    methods: {
    handleShow() {
    this.isShow=!this.isShow

    }
    }

    })
    </script>
    </html>

    8.4 ref属性

    1
    2
    3
    4
    ref放在标签上,拿到的是原生节点
    ref放在组件上,拿到的是组件对象,
    通过这种方式实现子传父(this.$refs.mychild.text)
    通过这种方式实现父传子(调用子组件方法传参数)
    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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <!-- 通过ref,获取input的值-->
    <input type="text" ref="mytext">
    <button @click="handleClick">点我</button>
    <child ref="mychild"></child>
    </div>
    </body>
    <script>
    Vue.component('child',{
    template:`<div>child</div>`,
    data(){
    return {
    text:'子组件数据'
    }
    },
    methods:{
    add(){
    console.log('子组件的add方法')
    }
    }
    })
    var vm = new Vue({
    el: '#box',
    data: {

    },
    methods: {
    handleClick() {
    console.log(this)
    //this.$refs.mytext 获取到input控件,取出value值
    console.log(this.$refs.mytext.value)
    console.log(this.$refs.mychild.text)
    // this.$refs.mychild.add()
    this.$refs.mychild.add('传递参数')

    }
    }

    })
    </script>
    </html>

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

    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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <child1></child1>
    <child2></child2>
    </div>
    </body>
    <script>
    var bus=new Vue() //new一个vue的实例,就是中央事件总线
    Vue.component('child1', {
    template: `<div>
    <input type="text" ref="mytext">
    <button @click="handleClick">点我</button>
    </div>`,
    methods:{
    handleClick(){
    bus.$emit('suibian',this.$refs.mytext.value) //发布消息,名字跟订阅消息名一致
    }
    }
    })
    Vue.component('child2', {
    template: `<div>
    <div>收到的消息 {{msg}}</div>
    </div>`,
    data(){
    return {msg:''}
    },
    mounted(){
    //生命周期,当前组件dom创建完后悔执行
    console.log('当前组件dom创建完后悔执行')
    //订阅消息
    bus.$on('suibian',(item)=>{
    console.log('收到了',item)
    this.msg=item
    })
    }
    })
    var vm = new Vue({
    el: '#box',
    data: {},
    methods: {
    handleClick() {
    console.log(this)
    //this.$refs.mytext 获取到input控件,取出value值
    console.log(this.$refs.mytext.value)
    console.log(this.$refs.mychild.text)
    // this.$refs.mychild.add()
    this.$refs.mychild.add('传递参数')

    }
    }

    })
    </script>
    </html>

    9 动态组件

    1
    2
    1 <component> 元素,动态地绑定多个组件到它的 is 属性
    2 <keep-alive> 保留状态,避免重新渲染

    9.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
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <ul>
    <li><a @click="who='child1'">首页</a></li>
    <li><a @click="who='child2'">商品</a></li>
    <li><a @click="who='child3'">购物车</a></li>
    </ul>
    <component :is="who"></component>
    </div>
    </body>
    <script>
    var bus = new Vue() //new一个vue的实例,就是中央事件总线
    Vue.component('child1', {
    template: `<div>
    首页
    </div>`,

    })
    Vue.component('child2', {
    template: `<div>
    商品
    </div>`,
    })
    Vue.component('child3', {
    template: `<div>
    购物车
    </div>`,
    })
    var vm = new Vue({
    el: '#box',
    data: {
    who:'child1'
    },

    })
    </script>
    </html>

    9.2 keep-alive使用

    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>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="box">
    <ul>
    <li><a @click="who='child1'">首页</a></li>
    <li><a @click="who='child2'">商品</a></li>
    <li><a @click="who='child3'">购物车</a></li>
    </ul>
    <keep-alive>
    <component :is="who"></component>
    </keep-alive>

    </div>
    </body>
    <script>
    var bus = new Vue() //new一个vue的实例,就是中央事件总线
    Vue.component('child1', {
    template: `<div>
    首页
    </div>`,

    })
    Vue.component('child2', {
    template: `<div>
    商品
    <input type="text">
    </div>`,
    })
    Vue.component('child3', {
    template: `<div>
    购物车
    </div>`,
    })
    var vm = new Vue({
    el: '#box',
    data: {
    who:'child1'
    },

    })
    </script>
    </html>
  • 相关阅读:
    在线预览Office文档
    花生壳内网穿透
    Net core跨域
    EF链表查询
    Python冒泡排序、选择排序、插入排序、希尔排序、归并排序
    竟然可以这样学python!
    如何使用python打印9乘9乘法口诀表?
    python爬取小视频
    —用python写PDF转换器
    从0到1搭建个人博客-Django(三)
  • 原文地址:https://www.cnblogs.com/bubu99/p/14742440.html
Copyright © 2020-2023  润新知