zoukankan      html  css  js  c++  java
  • 一步一步学Vue(三)

      接上篇,有同事看了我写的博客,觉得我这人不靠谱,文笔太白了,不够严肃,所以这次我一定要做一个严肃的人,写博客要有写博客的态度,第三篇开始我在考虑一个问题,会不会太着急了,要知道Vue的组件化时它的一个买点,现在还没有完全的过一遍其核心概念我就开始结合后端了,有点操之过急了,没写过这类博文,大家见谅。

      计划由于上述原因就会有些变动,会在接下来的文章中,先以demo的形式把一些核心概念先过一遍,这样我们才能写逼格很高的代码,要不写代码的时候总是捉急,就如以前学数学概念的时候,没学到的知识不能用,但是当前学的知识去解题又土又笨,学了后面的知识才发现原来解法如此可爱,好了,水话结束,我们以component开始我们的第三篇。

    1、什么是组件

      现在的前端框架,假如做宣传,不提组件化就感觉没有前途,三大主流框架(VueReactNg2+)都是完全支持组件化开发,那什么是组件化呢,这里我不会去拿百度google的结果贴出来,说一下简单的理解。我理解的组件化就是把内容分块,把业务分块,把结构分块,可能还有其它维度;所谓分块其实专业一点可以称为封装,封装、继承、多态是面向对象中的概念,但是也是代码重用的一种手段,我们对代码、对系统进行组件化也是代码重用的一种手段。

    举个简单的例子,在H5发布之后,新增了几个复杂标签,比如videoaudio等,这种本质上是什么东西呢,为什么浏览器遇到这个标签都能渲染出一个播放窗口呢,请看下图:

      我在Html中添加了一个video标签,打开chrome控制台查看元素看到的内容说明了其实video这个标签是有好多基本标签组成的,只不过我们看不到而已,里面的shadow,大家可以去查一下shadow dom,不只是这种标签,甚至一个简单的输入框也不是看到的那么简单:

      现在说一下vue中的组件或者前端框架中的组件,我们的目的也是构建类似video这样的标签,但是和video不同的是,video浏览器能识别,可以直接渲染,而我们定义的标签比如“my-video”浏览器不能识别无法渲染,但是我们借助框架的支持也可以渲染,这样不就相当于我们通过自定义标签的方式扩展了浏览器标签了么。

    组件一般分为ui组件和业务组件,ui组件由于其业务无关性,重用度比较高。业务组件只是系统内封装,方便组件消费者使用,组件化的系统一般结构都是从根组件开始下方为二级组件,三级组件,由组件构成树状结构。

    2、Vue中的组件

      Vue中注册组件有两种方式:全局注册和局部注册;全局注册通过component方法进行注册,在Vue实例对象的作用于内都可以直接使用;局部注册通过给Vue实例中的components对象添加属性的方式来注册,这种方式注册的组件只能在当前实例(可能是一个组件,也可能是根实例)中使用。

    1、全局注册

    Vue.component('comp1',options);

    2、局部注册

    var comp1={
    ....
    };
    new
    Vue({ el:'#app', components:{ 'comp1':comp1 } })

      已经了解了组建的注册机制,我们需要关注的另外一个点就是,当组件在创建注册后,怎么进行交互呢,比如父子组件,兄弟组件以什么机制来进行数据传输呢?传值是web开发中很重要的一个环节;在熟悉的angular中,父子controller传值可以通过$emit 和 $broadcast ,前者向上传播,后者向下传播;但是并不建议使用后者,因为后者在传递过程中会遍历所有的同级节点。而向组件或者指令中传值,angular有自己的绑定策略,那么Vue中是不是也有类似的机制呢。没错,在Vue中建议的方式就是“props in ,event out”。

      现在就以我们的todolist为例,简单说一下组件开发步骤:

      1、划分设计组件

      2、分析并实现组件定义

    首先对我们的todolist进行一下组件化划分,按照我们对业务的理解,可以划分为以下几个组件:

    其中包含todo-container容器组件,该组件用来管理其它组件;search-bar组件,todo-form组件、todolist组件、todolist组件的子组件todoitem组件。

    下面我们基于上图,对我们的组件进行简单的定义:

    var TodoItem=(function(){
        var id=1;
        return function(title,desc){
            this.title=title;
            this.desc=desc;
        }
    })();
    /**
     * 搜索组件
     */
    var searchBar={
        template:`
            //TODO:
        `,
        data:function(){
            return {
                keyword:''
            }
        },
        methods:{
            search:function(){
                this.$emit('onsearch',this.keyword);
            }
        }
    
    }
    /**
     * 表单组件
     */
    var todoForm={
        template:``,
        data:function(){
            return {
                id:'',
                title:'',
                desc:''
            }
        },
        methods:{
            ok:function(){
                this.$emit('onsave',new TodoItem(this.title,this.desc));
    
                this.title=this.desc='';
            }
        }
    
    }
    /**
     * 列表项组件
     */
    var todoItem={
        template:`
        //TODO:
        `,
        props:['todo'],
        methods:{
            edit:function(){
                this.$emit('onedit',this.todo.id);
            },
            remove:function(){
                this.$emit('onremove',this.todo.id);
            }
        }
    }
    /**
     * 列表组件
     */
    var todoList={
        template:`
            ...
            <todo-item  v-for="item in items" :todo="item"  @onedit="edit($event)" @onremove="remove($event)"></todo-item>
        `,
        props:['items'],
        components:{
            'todo-item':todoItem
        },
        methods:{
            edit:function($e){
                this.$emit('onedit',$e);
            },
            remove:function($e){
                this.$emit('onremove',$e);
            }
        }
    }
    /**
     * 容器组件
     * 说明:容器组件包括三个字组件
     */
    var todoContainer={
        template:`
            <div class="container">
                <search-bar @onsearch="search($event)"></search-bar>
                <todo-form @onsave="save($event)"></todo-form>
                <todo-list :items="todos" @onremove="remove($event)" @onedit="edit($event)"></todo-list>
            </div>
        `,
        data:function(){
            return {
                items:[]
            }
        },
        components:{
            'search-bar':searchBar,
            'todo-form':todoForm,
            'todo-list':todoList
        },
        methods:{
            search:function($e){
                console.log('TODO search');
            },
            save:function($e){
                console.log('TODO save');
            },
            remove:function($e){
                console.log('TODO remove');
            },
            edit:function($e){
                console.log('TODO edit');
            }
        }
    }
    
    var app=new Vue({
        el:'#app',
        components:{
            'todo-container':todoContainer
        }
    });
    
    /**
     * 
     * 
     * <div id="app">
     *     <todo-container></todo-container>
     * </app>
     */

    上面的为代码(应该算半成品代码),代表了基本的定义,以及依赖关系,最后的注释表示最终使用方式,具体可运行的代码我会放在下一篇细讲,并分析代码这样写的原因,大家可以根据组件设计草图,自己按照文旦去写一下自己的实现,然后通过对比我的实现比较一下优劣,可以在下方评论中说出你的思路或者好的想法,欢迎脑爆!希望大家先写出可运行的代码,周五晚上是大家最向往的时候,have a good weekend!!! 休息一下。

  • 相关阅读:
    龙小树|第一篇博客随笔
    机器学习相关网址
    希腊字母表
    博客园美化
    论文检索常用网站
    这些年,我用过的良心网站,分享给大家
    MATLAB小函数:展示灰度图像数据集的部分样例
    基于图嵌入的高斯混合变分自编码器的深度聚类(Deep Clustering by Gaussian Mixture Variational Autoencoders with Graph Embedding, DGG)
    MATLAB实例:二维散点图
    MATLAB实例:多元函数拟合(线性与非线性)
  • 原文地址:https://www.cnblogs.com/Johnzhang/p/7218830.html
Copyright © 2011-2022 走看看