Vue组件实战

博客 动态
0 212
羽尘
羽尘 2022-04-17 17:58:05
悬赏:0 积分 收藏

Vue 组件实战

Vue 组件实战 axios实现数据请求、计算属性、监听属性、局部组件、全局组件、组件通信之父传子、组件通信之子传父、 ref属性(组件间通信)、动态组件和keep-alive

目录
  • Vue 组件
    • axios实现数据请求
    • 计算属性
      • 案例一:首字母大写
      • 案例二:过滤案例
    • 监听属性
    • 局部组件
    • 全局组件
    • 组件通信之父传子
    • 组件通信之子传父
    • ref属性(组件间通信)
      • 普通标签使用
      • 组件使用ref属性
    • 事件总线(不常用)
    • 动态组件和keep-alive

Vue 组件

Vue 生命周期钩子

axios实现数据请求

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="./js/vue.js"></script>    <script src="https://unpkg.com/axios/dist/axios.min.js"></script></head><body><div id="app">    <ul>        <li v-for="film in films_list">            <p>电影名字是:{{film.name}}</p>            <img :src="film.poster" alt="" width="100px" height="150px">            <p>电影介绍:{{film.synopsis}}</p>        </li>    </ul></div></body><script>    var vm = new Vue({        el: '#app',        data: {            films_list:[]        },        created() {            axios.get('http://127.0.0.1:5000/films').then(res => {                console.log(res.data)                this.films_list=res.data.data.films            })        }    })</script></html>
from flask import Flask,make_response,jsonifyapp=Flask(__name__)@app.route('/films')def films():    import json    with open('./movie.json','r',encoding='utf-8') as f:        res=json.load(f)    obj = make_response(jsonify(res))    obj.headers['Access-Control-Allow-Origin']='*'    return objif __name__ == '__main__':    app.run()

image


计算属性

我们可以通过计算属性computed来缓存计算,什么意思呢?

在Vue中我们可以使用插值来展示数据,插值的普通函数,只要页面一刷新,函数就会重新运算,不管和函数有关没关的值都会变,函数也会重新计算,导致运行效率降低;

那么我们可以将自定义函数写在computed中来控制,把函数当成属性来用,调用不需要加括号,只有这个函数使用的属性(变量)发生变化,函数才重新运算,这样做可以减轻压力,减少资源浪费

案例一:首字母大写

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>计算属性</title>    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>    <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/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>    <script src="./js/vue.js"></script></head><body><div id="app">    <div >        输入内容:<input type="text" v-model="mytext"> ----》 {{mytext.substring(0,1).toUpperCase()+mytext.substring(1)}}        <br><br>        <p>函数绑定(会刷新页面,也不推荐):<input type="text" :value="getName()"></p>        <p>计算属性(推荐):<input type="text" :value="getName1"></p>    </div>    <hr>    <div >         <p>输入内容:<input type="text" v-model="mytext1"> -----》{{mytext1}}</p>    </div></div></body><script>    var vm = new Vue({        el: '#app',        data: {            mytext: '',            mytext1:''        },        methods:{            getName(){                console.log('函数方式,我执行了')                return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)            }        },        //计算属性        computed:{            getName1(){                console.log('计算属性,我执行了')                return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)            }        }    })</script></html>

计算属性

我们可以发现只有和属性相关的才会打印,如果下面输入内容只是打印了普通函数,就算函数内和mytext1不相关

案例二:过滤案例

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>过滤案例</title>    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script></head><body><div id="box">    <p><input type="text" v-model="myText"  placeholder="请输入要筛选的内容:"></p>    <ul>        <li v-for="data in newList">{{data}}</li>    </ul></div></body><script>    var vm = new Vue({        el: '#box',        data: {            myText: '',            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],        },        computed:{            newList(){                var _this = this                console.log('执行了',_this)                 var datalist2 = _this.dataList.filter(function(item){                    console.log(_this)                     return item.indexOf(_this.myText) > -1                })                return datalist2            }        }    })</script></html>

计算属性2



监听属性

watch来设置监听属性,当mytext发生变化,就会执行和mytext绑定的函数方法

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="./js/vue.js"></script></head><body><div id="app">    <input type="text" v-model="mytext">--->{{mytext}}</div></body><script>    var vm = new Vue({        el: '#app',        data: {            mytext: '',        },        watch: {            // 只要mytext发生变化,就会执行该函数            mytext: function () {                console.log('我变化了,执行')            }        }    })</script></html>

监听属性


局部组件

写在components里的是局部组件,位置被限制,只能再局部使用

比如如下例子中,Top组件只能在只能再id为app的标签(div)内使用, Top组件内如果想再定义子组件,只能在该组件内的template中的div内使用

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="./js/vue.js"></script></head><body><div id="app">    <Top></Top>    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>    <Bottom></Bottom></div></body><script>    var vm = new Vue({        el: '#app',        data: {},        // 定义再这里面的叫局部组件,只能再局部使用,只能再id为app的标签内使用        components: {            'Top': {                //写在一个div里                template: `                    <div>                        <h1 >{{name}}</h1>                        <hr>                        <button @click="handleC">点我看美女</button>                    </div>                `,                //data是函数,可以设置返回值                data() {                    return {                        name: "我是头部"                    }                },                methods: {                    handleC() {                        alert('美女')                    }                },            },            'Bottom': {                template: `                    <div>                        <hr>                        <h1 >{{name}}</h1>                    </div>                `,                data() {                    return {                        name: "我是尾部"                    }                },            },        },    })</script></html>

局部组件


全局组件

任意位置都可以使用,但是也得是在vue实例托管的div范围内

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="./js/vue.js"></script></head><body><div id="app">    <top></top></div></body><script>    // 定义全局组件,任意位置都可以用,局部内也可以使用    Vue.component('top', {            template: `                <div>                    <h1 >{{name}}</h1>                    <hr>                    <button @click="handleC">点我看美女</button>                </div>            `,            data() {                return {                    name: "我是头部"                }            },            methods: {                handleC() {                    alert('美女')                }            },        },)    var vm = new Vue({        el: '#app',    })</script></html>

全局组件


组件通信之父传子

组件间data数据不同享,数据传递,如果我们想从父组件传递到子组件数据通过props自定义属性来实现,比如如下例子:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>    <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/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>    <script src="./js/vue.js"></script></head><body><div id="app">    子组件显示:<top :value="handleName"></top>    <hr>    父组件输入内容:<input type="text" v-model="handleName"></div></body><script>    Vue.component('top', {        template: ` <div>                    <h1 >{{value}}</h1>                    </div>             `,        // 必须叫props,数组内放自定义属性的名字        props:{            value: String,  // key是自定义属性名,value是类型名,如果是别的类型就报错        },        //props也可以写成数组的形式,不带验证功能        // props:['value',]    })    var vm = new Vue({        el: '#app',        data: {            handleName: ''        }    })</script></html>

父传子


组件通信之子传父

ps:Vue内置的对象都以$xx出现

我们可以通过自定义事件来实现子组件向父组件传递数据,在子组件中使用$emit('自定义事件',参数)来实现

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>    <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/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>    <script src="./js/vue.js"></script></head><body><div id="app"><top @myevent="handleRecv"></top>    <hr>  <h1 >父组件</h1> <p>接收子组件发送的数据:{{childText}}</p></div></body><script>    Vue.component('top', {        template: ` <div>                        <h1 >{{myheader}}</h1>                        <p>子组件输入内容:<input type="text" v-model="text"></p>                        <p><button   @click="handleSend">向父组件发送数据</button></p>                    </div>             `,        data(){            return {                myheader:'子组件',                text:''            }        },        methods:{            handleSend(){                //myevent是自定义事件,代表将子组件的text交给myevent事件处理                this.$emit('myevent',this.text)            }        }    })    var vm = new Vue({        el: '#app',        data: {            //接收子组件的数据            childText:''        },        methods: {            handleRecv(data){                // 接收参数,赋值给父组件的childText                this.childText=data            }        }    })</script></html>

子传父


ref属性(组件间通信)

普通标签使用

普通标签使用ref属性,通过$refs获取到的就是ref属性所在的标签,获取到的是一个对象,如果多个标签写了ref属性,那么就将所有带ref属性的标签弄到一个对象中,可以对html进行操作设置等,如下示例:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>    <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/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>    <script src="./js/vue.js"></script></head><body><div id="app">    <h1 >普通标签使用ref</h1>    <p><input type="text" ref="myinput"></p>    <p><img src="" height="100px" width="100px" ref="myimg"></p>    <p><button @click="handleC">点我</button></p></div></body><script>    let vm = new Vue({        el: '#app',        data: {             text:''        },        methods: {            handleC(){                console.log('我被点了')                console.log(this.$refs)  // 是所有标签写了ref属性的对象{myinput:真正的标签,myimg:真正的标签}                console.log(this.$refs.myinput.value)                //设置值                this.$refs.myinput.value='HammerZe'                //设置src属性,显示图片                this.$refs.myimg.src='https://img0.baidu.com/it/u=3608430476,1945954109&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=494'            }        }    })</script></html>

ref属性1

组件使用ref属性

ref属性,如果放在组件上,就是当前组件对象

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>    <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/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>    <script src="./js/vue.js"></script></head><body><div id="app"><!-- 组件使用ref属性   --><top ref="top"></top><p>通信:<input type="text" v-model="text"></p><p>父组件按钮:<button @click="handleC">点我</button></p></p></div></body><script>   Vue.component('top', {        template: `            <div>                <h1>{{myheader}}</h1>                <p>子组件按钮:<button @click="handleC">点我看美女</button></p>                <hr>            </div>        `,        data() {            return {                myheader: "头部",            }        },        methods:{            handleC(){                alert("美女")            }        }    },)    let vm = new Vue({        el: '#app',        data: {             text:''        },        methods: {        //放在组件上        handleC() {             console.log(this.$refs.top) //VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}            /*子传父*/            // 父组件拿子组件的值            console.log(this.$refs.top.myheader)            // this.text=this.$refs.top.myheader            // 父组件调用子组件的方法            this.$refs.top.handleC()            /*父传子*/            this.$refs.top.myheader=this.text        }        }    })</script></html>

ref属性2

事件总线(不常用)

<!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>

动态组件和keep-alive

动态组件:实现点击不同的连接显示不同的页面,实现跳转,使用component标签,用is属性绑定,指定哪个显示哪个

keep-alive:通过keep-alive标签实现组件不销毁,保留原来输入的内容

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="./js/vue.js"></script></head><style>    #menu {        font-size: 18px;        font-weight: bold;    }    #menu li {        text-decoration: none; /*去掉前面的圆点*/        list-style: none;        float: left;        margin-right: 20px;    }</style><body><div id="app">    <ul id="menu">        <li @click="changeC('index')">首页</li> &nbsp;        <li @click="changeC('order')" >订单</li>        <li @click="changeC('good')">商品</li>    </ul>    <keep-alive>        <component :is='who'></component>    </keep-alive></div></body><script>    //三个组件    Vue.component('index', {        template: `            <div >                <h1>首页内容</h1>            </div>        `,    },)    //保留输入的订单信息    Vue.component('order', {        template: `            <div>                <h1>订单内容</h1>                请输入要查询的订单:<input type="text">            </div>        `,    },)    Vue.component('good', {        template: `            <div>                <h1>商品内容</h1>            </div>        `,    },)    var vm = new Vue({        el: '#app',        data: {            //默认显示index            who: 'index'        },        methods: {            changeC(data) {                this.who = data            }        }    })</script></html>

动态组件

posted @ 2022-04-17 17:53 HammerZe 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员