vue学习回顾第三天

Vue组件

组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。

组件的创建

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue2.js"></script>
</head>
<body>
<!--模板要在不受vue控制的地方创建-->
<template id="three">
    <div>方式3通过模板</div>
</template>
<!--模板的第二种使用方式-->
<script type="x-template" id="three2">
<div>模板的另一种使用方式</div>
</script>
<div id="app">
    <!--组件的使用与HTML标签一样-->
    <index-a></index-a>
    <index-b></index-b>
    <index-c></index-c>
    <index-d></index-d>
</div>
</body>
<script>

    // 注意:1. 模板template中只能有一个根节点;2. 组件的名字,如果采用驼峰命令的话,在使用的时候,就要加上 “-”,比如组件名字叫indexA,那么在使用的时候就叫index-a
    // 第一种:使用Vue.extend()和Vue.component()两个方法创建
    // Vue.extend()函数会返回一个组件的构造器,它里面包含一个参数,它是一个对象,里面是一些配置项
    // Vue.component()函数会利用Vue.extend()返回的构造器创建一个组件的实例,它有两个参数,一个是组件的名字,另一个组件的构造器
    let Index=Vue.extend({
        template:"<div>我是首页</div>"
    });
    //第一个参数为组件名字,第二个为组件构造器
    Vue.component("indexA",Index);

    //方式二创建组件:使用Vue.component()创建,本质上还是调用vue.extend()方法
    Vue.component("indexB",{
        template:"<div>第二种方式创建</div>"
    });


    //第三种方式创建
    //通过指定模板创建,适用于模板内容特别多的时候
    Vue.component("indexC",{
        template:"#three"
    });
    Vue.component("indexD",{
        template:"#three2"
    });
    let vm=new Vue({
        el:"#app",
        data:{

        }
    })
</script>
</html>

组件中使用事件和指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件中使用事件和指令</title>
    <script src="vue2.js"></script>
</head>
<body>
<div id="app">
    <click></click>
</div>

</body>
<script>
    //注册组件
    // 构造 Vue 实例时传入的各种选项大多数都可以在组件里使用,但注意data必须是一个函数
    Vue.component("click",{
        template:"<div>{{msg}}<button @click='change'>改变</button></div>",
       //data必须是一个函数
        data(){
            return{msg:"hello"
            }

        },
        methods:{
            change(){
                this.msg="world"
            }
        }
    })
    let vm=new Vue({
        el:'#app',
        data:{

        }
    })
</script>
</html>

父子组件

  • 父子组件的创建
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件的创建</title>
    <script src="vue2.js"></script>
</head>
<body>
<div id="app">
    <father>

    </father>
   <!-- <son></son>错误用法,子组件在父组件中使用-->
</div>
</body>
<script>
    //创建父组件
    Vue.component("father",{
        //子组件要在父组件中使用
        template:'<div>我是父组件<son></son></div>',
        //通过components创建子组件
        components:{
            //son就是子组件的名字
            son:{
                template:"<div>我是子组件</div>"
            }
        }
    })
    let vm=new Vue({
        el:"#app",
        data:{

        }
    })
</script>
</html>
  • 组件之间的传值
    1父组件传值给子组件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子组件获取父组件中的值</title>
    <script src="vue2.js"></script>
</head>
<body>
<div id="app">
    <father></father>
</div>
</body>
<script>
    Vue.component("father",{
        // 2. 在使用子组件的地方,通过v-bind指令给子组件中的props赋值
        template:'<div>我是一个父亲,我儿子的名字叫{{mySonName}}<p><son :myName="mySonName"></son></p></div>',
        data(){
            return{
                mySonName:"小明"
            }
        },
        components:{

            son:{
                // 1. 声明props,它的作用是:用来接收从父组件传递过来的值
                // props可以跟一个数组,数组里面的值是一个一个的字符串,这个字符串可以当成属性来使用
                props:['myName'],
                template:'<div>我是儿子,我爸爸给我起名叫{{myName}}</div>'
            }
        }
    });

    let vm=new Vue({
        el:"#app",
        data:{

        }
    })
</script>
</html>

2 子组件传值给父组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父组件获取子组件中的值</title>
    <script src="vue2.js"></script>
</head>
<body>
<div id="app">
    <father></father>
</div>
</body>
<script>

    Vue.component("father",{
        //通过监听事件获取数据
        template:'<div>我是爸爸,我儿子告诉我他的名字是{{mySonName}}<p><son @tellMyName="getMySonName"></son></p></div>',
        data(){
            return{
                mySonName:""
            }
        },
        methods:{
            //获取子组件上传的数据,默认参数代表子组件上传的数据
            getMySonName(data){
                this.mySonName=data;
            }
        },
        components:{
            son:{
                template:'<button @click="emitMyName">告诉我父亲我的名字</button>',
                data(){
                    return{
                        myName:"小花"
                    }
                },
                methods:{
                    //传递数据给父组件使用$emit方法,有两个参数,一个是事件名,另一个是要传递的数据
                    emitMyName(){
                        this.$emit("tellMyName",this.myName)
                    }
                }
            }
        }
    })
    let vm=new Vue({
        el:"#app",
        data:{

        }
    })
</script>
</html>

3 兄弟组件之间传值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>兄弟组件之间传值</title>
    <script src="vue2.js"></script>
</head>
<body>
<div id="app">
    <father>

    </father>
</div>
</body>
<script>
    //1 创建一个空的vue实例,作为事件总线
    let eventBus=new Vue();
    Vue.component("father",{
        template:`<div>父组件
            <son></son>
            <daughter></daughter>
</div>`,
        components:{
            son:{
                data(){
                    return{
                        mySisterName:""
                    }
                },
                template:`<div>我妹妹的名字叫{{mySisterName}}</div>`,
               mounted(){
                    // 3 通过eventbus的$on()方法去监听兄弟节点发射过来的事件
                   //两个参数,事件名称和回调函数,参数就是传过来的数据
                    eventBus.$on('tellBroMyName',data=>{
                        this.mySisterName=data;
                    })
               }
            },
            daughter:{
                data(){
                    return{
                        myName:"小红"
                    }
                },
                template:`<button @click="emitMyName">点击就告诉哥哥我的名字叫{{myName}}</button>`,
                methods:{
                    emitMyName(){
                        //2 通过事件总线的$emit方法发送一个事件和传递的数据
                        eventBus.$emit("tellBroMyName",this.myName)
                    }
                }
            }
        }
    })
    let vm=new Vue({
        el:"#app",
        data:{

        }
    })
</script>
</html>

动态组件

<body>
    <div id="app">
      <ul>
        <li @click="currentCom='index'"><a href="#">首页</a></li>
        <li @click="currentCom='productType'"><a href="#">蔬菜</a></li>
        <li @click="currentCom='productType'"><a href="#">水果</a></li>
        <li @click="currentCom='productType'"><a href="#">肉类</a></li>
      </ul>
      <!-- 利用component标签创建动态组件,它的is属性指向谁,就显示哪个组件 -->
      <component :is="currentCom"></component>
    </div>
    <script>
      // 首页组件
      Vue.component('index', {
        template: '<div>首页</div>'
      })
      Vue.component('productType', {
        template: '<div>这里显示商品编号</div>'
      })
      var vm = new Vue({
        el: '#app',
        data: {
          currentCom: ''
        }
      })
    </script>
  </body>

局部过滤器和局部指令

<body>
    <div id="app">
      <one></one>
      <two></two>
    </div>
    <script>
      // 全局自定义指令可以在任何组件中使用
        Vue.directive('mycolor', {
          inserted(el, binding) {
            console.log(binding);
            // binding.value可以获取传入自定义指令中的属性的值
            el.style.color = binding.value
          }
        })
      // 不管是局部自定义指令还是局部过滤器都只能在当前组件内使用,脱离当前组件无效
      // 局部过滤器通过在组件内部使用filters属性创建
      Vue.component('one', {
        data () {
          return {
            time: new Date(),
            color: 'red'
          }
        },
        template: `
                      <div>
                        <p>{{time | fmtTime}}</p>
                        <input type="text" v-mycolor="color">
                      </div>
        `,
          //filters创建局部过滤器
        filters: {
          fmtTime(time) {
            console.log(time);
            var y = time.getFullYear();
            var m = time.getMonth() + 1;
            var d = time.getDate();
            return y + '/' + m + '/' + d
          }
        }
      })
      // 局部自定义指令通过在组件内部使用directives属性创建
      Vue.component('two', {
        data () {
          return {
            time: new Date(),
            color: 'red'
          }
        },
        template: `
                      <div>
                        <p>{{time}}</p>
                        <input type="text" v-myfocus v-mycolor="color">
                      </div>
        `,
        directives: {
          myfocus: {
            inserted(el, binding) {
              console.log(el);
              console.log(binding);
              el.focus()
            }
          }
        }
      })
      var vm = new Vue({
        el: '#app',
        data: {

        }
      })
    </script>
  </body>

生命周期钩子

<body>
    <div id="app">
        <p>{{info}}</p>
        <button @click="info='hello1'">更新info</button>
        <button @click="destroy">销毁实例</button>
    </div>
    <script>
        var myVm = new Vue({
            el: "#app",
            data: {
                info: "hello"
            },
            // 在实例初始化之后,数据观测 (data observer) 和 event/watcher 配置之前被调用。
            beforeCreate: function () {
                console.log("===============beforeCreate============================================")
                // $el表示Vue 实例使用的根 DOM 元素。
                console.log('$el', this.$el);
                // $data Vue 实例观察的数据对象
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            // 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,dom还未生成,$el 属性目前不可见。
            created: function () {
                console.log("===============created=======================================")
                console.log('$el', this.$el);
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            // 模板编译挂载之前调用,首先会判断对象是否有el选项。如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)。接着判断是否有template属性,有的话就以template属性中的值作为模板,如果没有的话,就以el属性指向的作为模板。这里会生成vm.$el,但指令尚未被解析
            beforeMount: function () {
                console.log("===============beforeMount=========================================")
                console.log('$el', this.$el);
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            // 模板编译挂载之后调用,vm.$el替换掉el指向的dom
            mounted: function () {
                console.log("===============mounted===========================================")
                console.log('$el', this.$el);
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            // 数据变更导致虚拟DOM重新渲染之前调用
            beforeUpdate: function () {
                console.log("===============beforeUpdate============================================");

            },
            // 数据变更导致虚拟DOM重新渲染之后调用
            updated: function () {
                console.log("===============updated======================================================");
            },
            // 实例销毁之前调用,在这一步,实例完全可用
            beforeDestroy: function () {
                console.log("===============beforeDestroy===============================================")
                console.log('$el', this.$el);
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            // vue实例指向的所有东西解除绑定,包括watcher、事件、所以的子组件,后续就不再受vue实例控制了
            destroyed: function () {
                console.log("===============destroyed================================================")
                console.log('$el', this.$el);
                console.log('$data', this.$data);
                console.log("info:", this.info)
            },
            methods: {
                destroy() {
                    // 表示销毁组件
                    this.$destroy()
                },
                udpateinfo() {
                    this.info = 'hello2'
                }
            }
        })
    </script>
</body>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容