美文网首页
VUE02:Vue组件

VUE02:Vue组件

作者: 杨强AT南京 | 来源:发表于2019-10-21 08:46 被阅读0次

  前后端分离使得前端可以想开发后台一样开发,这种思想指导下的Vue是比较常用框架,这个框架的最大特色是页面组件化,为后面Vue组件单文件化提供基础;本主题的组件技术核心是两个部分:
  1. 内置组件注册与实现;
  2. 组件路由;


  单文件组件会在webpack框架下使用Vue-Loader实现。


页面组件(Component)

  • 页面设计是非常繁琐的事情,Web页面尽管提供了最基本的HTML标签(Tag:也称标记)来完成页面最基本的构成元素,但是提供更加高级的UI元素封装可以简化页面实现的复杂度。Vue提供了组件封装机制:

    • 注册一个组件
      • 使用Vue的全局函数component实现注册
    • 在HTML中使用组件
      • 像HTML标签一样使用组件
  • Web页面模块化是开发者的需求,基本上所有Web框架都提供:

    • Struts中Tag标签封装有页面模块化的框架;
    • Spring框架中也有页面模块化封装;
    • jQuery纯前端框架也提供模块化封装(通过样式分类封装实现);

Vue.component函数与全局组件

函数定义


    Vue.component( id, [definition] )

  • 参数说明:
    • id:字符串类型,用来指定组件名
    • [definition]:选项类型{},遵循Vue的选项格式。
      1. 数据选项
        • data/props/propsData/computed/methods/watch
      2. DOM选项
        • el/template/render/renderError
      3. 声明周期钩子选项
        • beforeCreate/created/beforeMount/mounted/beforeUpdate/updated
        • activated/deactivated/beforeDestroy/destroyed/errorCaptured
      4. 资源选项
        • directives/filters/compnents
      5. 组合选项
        • parent/mixins/extends/provide/inject
      6. 其他选项
        • name/delimiters/functional/model/inheritAttrs/comments

使用例子

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue 全局组件</title>
    <script src="vue.min.js"></script>
</head>
<body>
    <main id="main">
        <!--3. 使用新注册的组件-->
        <mydiv></mydiv>
    </main>

    <script type="text/javascript">
        // 1.注册组件
        Vue.component(
            "mydiv",
            {              // 选项格式:JSON对象格式
                template: "<div style='width:200px; height:200px;background-color:red;'>定制组件</div>"
            });
        // 2. 创建Vue对象,该对象已经包含新注册的组件
        var vm = new Vue(
            {
                el: "#main"
            }
        );

    </script>

</body>
</html>

components选项与局部组件

  • Vue对象的components选项用来定义(注册)局部组件;而且可以同时定义多个。语法格式与全局组件的定义一样。下面直接使用例子说明:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue 局部组件</title>
    <script src="vue.min.js"></script>
</head>
<body>
    <main id="main">
        <!--2. 使用注册的局部组件-->
        <mydiv></mydiv>
        <yourdiv></yourdiv>
    </main>

    <script type="text/javascript">
        // 1. 注册局部组件(注册两个)
        var vm = new Vue(
            {
                el: "#main",
                components: {
                    "mydiv":{              // 选项格式:JSON对象格式
                        template: "<div style='width:200px; height:200px;background-color:red;'>定制局部组件一</div>"
                    },
                    "yourdiv":{              // 选项格式:JSON对象格式
                        template: "<div style='width:200px; height:200px;background-color:blue;'>定制局部组件二</div>"
                    },
                }
            }
        );

    </script>

</body>
</html>


props选项与组件的属性

props语法说明


    Array<string> | Object

  • 语法说明:
    • props的类型可以是如下两种:
      1. 数组,用来指定属性列表
      2. JSON对象,用来指定高级配置选项;选项包含:
        1. type:可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。
        2. default:为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
        3. required:逻辑值true或者false,定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 prop 没有被传入的,则一个控制台警告将会被抛出。
        4. validator:自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。
  • 说明:
    • 如果只有type选项,可以直接使用。
    • 其中的required在html宽松的语法下,不一定有效果;
    • 对类型的约束在Boolean职情况下也比较宽松。

数组的使用例子

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue 组件数组属性</title>
    <script src="vue.min.js"></script>
</head>
<body>
    <main id="main">
        <!--3. 使用新注册的组件-->
        <!--注意:定制组件的属性也可以绑定数据-->
        <mydiv p1="属性-1" p2="属性-2"></mydiv>
    </main>

    <script type="text/javascript">
        // 1.注册组件
        Vue.component(
            "mydiv",
            {              // 选项格式:JSON对象格式
                template: "<div style='width:200px; height:200px;background-color:red;'>定制组件:{{p1}}-{{p2}}</div>",
                props: ["p1","p2"]
            });
        // 2. 创建Vue对象,该对象已经包含新注册的组件
        var vm = new Vue(
            {
                el: "#main"
            }
        );

    </script>

</body>
</html>

对象的使用例子

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue 组件对象属性</title>
    <script src="vue.min.js"></script>
</head>
<body>
    <main id="main">
        <!--3. 使用新注册的组件-->
        <!--注意:定制组件的属性也可以绑定数据-->
        <mydiv p1="True" p2="AAA"></mydiv>
        <mydiv p2="aaa"></mydiv>
    </main>

    <script type="text/javascript">
        // 1.注册组件
        Vue.component(
            "mydiv",
            {              // 选项格式:JSON对象格式
                template: "<div style='width:200px; height:200px;background-color:red;'>定制组件:{{p1}}-{{p2}}</div>",
                props: {
                    p1: [Boolean,String],
                    p2: {
                        type:Number,
                        default:30,
                        required:true,
                        validator:function (value){
                            console.log('hello');
                            return true;
                        }
                    }
                }
            });
        // 2. 创建Vue对象,该对象已经包含新注册的组件
        var vm = new Vue(
            {
                el: "#main"
            }
        );

    </script>

</body>
</html>


组件的自定义事件

  • 自定义事件使用$emit指令触发事件

  • 注意:

    • 组件的自定义事件只能定制的注册组件能处理;其他组件无法接收(原生的标记组件无法接收);

$emit的定义

    vm.$emit( eventName, […args] )
  • 参数说明
    • eventName:事件名
    • […args]:传递给事件处理函数的参数;

例子

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue 组件对象属性</title>
    <script src="vue.min.js"></script>
</head>
<body>
    <div id="main">
        <mybutton v-on:myevent="myevent_handler"></mybutton>
        <!--下面的事件无法接收-->
        <!--
        <div v-on:myevent="myevent_handler">被触发的按钮</div>   
        -->
    </div>

    <script type="text/javascript">
        /*
        组件的事件只能发送给自己,其他组件接收不到这个时间信号。
        */

        Vue.component(
            "mybutton",
            {              // 选项格式:JSON对象格式
                template: "<button v-on:click='click_handler'>点击</button>",
                methods: {
                    click_handler: function(){
                        this.$emit("myevent");    // 抛出事件
                    },
                }
            }
        );
        var vm = new Vue(
            {
                el: "#main",
                data:{
                    data1: "数据",
                },
                methods: {
                    myevent_handler: function(){    // 事件处理函数
                        alert("定制事件被触发!");
                    }
                }
            }
        );

    </script>

</body>
</html>

页面路由实现数据区导航

  • Vue的路由需要单独的库,下载地址:

    • https://unpkg.com/vue-router/dist/vue-router.js
  • 页面路由主要管理页面链接导航,以及导航的会话历史数据与跟踪;如果仅仅是超链接,则使用比较简单。

  • 注意:

    • 页面路由会添加#实现是内部锚点导航;

使用路由实现链接

  • 使用vue-router的<router-link>定制标记即可;使用方式两个部分:

    1. 使用router-link标记导航;
    2. 挂载router-link到Vue环境;
  • 理由使用例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue-Router</title>
    <script src="vue.min.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="main">
        <!--1. 使用router实现导航菜单-->
        <router-link to="/url1">到组件1</router-link>
        <router-link to="/url2">到组件2</router-link>
        <!--2. 导航组件显示区:渲染的位置-->
        <br>
        <router-view></router-view>
    </div>
    <script>
        const target1 = {template:"<button>链接1</button"};
        const target2 = {template:"<input type='text' value='请输入'/>"};
        // 3. 定义router对象
        const router = new VueRouter({
            // mode: "history",    // 默认使用#实现锚点导航hash,history使用相对url导航(站点资源)。
            routes: [
                {path: '/url1', component: target1},
                {path: '/url2', component: target2},
            ],
        });
        // 4. 挂载router对象
        var vm = new Vue({
            router
        }
        ).$mount('#main');
    </script>
</body>
</html>

  • 说明:
    • 导航还有很多内容,包括querystring等处理,链接嵌套等,这里暂时不介绍,仅仅了解router提供的设计模式的优点。

使用html文件作为路由组件

  • 可以在router-link中直接使用外部html文件,但是需要设置下router的model。下面是例子:
    • hash与hostory不能混用。
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue-Router</title>
    <script src="vue.min.js"></script>
    <script src="vue-router.js"></script>
    <link rel="shortcut icon" href="#" />
</head>
<body>
    <div id="main">
        <!--1. 使用router实现导航菜单-->
        <router-link to="./v01_vue_data.html">到组件1</router-link>
        <!--2. 导航组件显示区:渲染的位置-->
        <br>
        <router-view></router-view>
    </div>
    <script>
        const target2 = {template:"<input type='text' value='请输入'/>"};
        // 3. 定义router对象
        const router = new VueRouter({
            mode: "history",    // 默认使用#实现锚点hash导航,history使用相对url导航(站点资源)。
        });
        // 4. 挂载router对象
        var vm = new Vue({
            router
        }
        ).$mount('#main');
    </script>
</body>
</html>

多视图路由

  • 可以一个路由url使用的是default组件,一个路由url可以绑定多个组件,每个组件指定名字,改名字可以对应显示在不同的视图中,下面是使用例子:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue-Router</title>
    <script src="vue.min.js"></script>
    <script src="vue-router.js"></script>
    <link rel="shortcut icon" href="#" />
</head>
<body>
    <div id="main">
        <!--视图激活方式:(一)-->
        <!-- <router-link to="/url1">链接</router-link> -->
        <router-view></router-view>
        <router-view name="v1"></router-view>
        <router-view name="v2"></router-view>
    </div>
    <script>
        const target1 = {template:"<button>链接1</button"};
        const target2 = {template:"<input type='text' value='请输入'/>"};
        const target3 = {template:"<hr>"};
        // 3. 定义router对象
        const router = new VueRouter({
            mode: "hash", 
            routes: [
                {
                    path: '/url1', 
                    components: {
                        default: target1,
                        v1: target2,
                        v2:target3
                    }
                },
            ],
        });
        // 4. 挂载router对象
        var vm = new Vue({
            router
        }
        ).$mount('#main');
        // 激活方式:(二)
        router.push("url1");
    </script>
</body>
</html>

说明

  • vue与vue-router只是解决了页面模块化问题,实际上并没有提供vue文件作为组件的功能与机制;
    • 把vue文件作为组件的解决方案是vue-loader,他会对vue文件进行解析处理(主要处理html,css与javascript三个部分),vue-loader使用的是javascript服务器脚本ES6以上版本,这个需要专门的javascript运行环境,node.js就是Javascript的运行环境(号称Javascript虚拟机,与JVM同等地位)
    • 使用浏览器javascript自己组织多个页面太痛苦了(python等服务器脚本语言目前还有ES6这种彪悍的对多个页面组织的封装框架),我们引入基于ES6的Web前端框架来解决多个页面组织的问题,那我们就需要了解下node.js,然后了解Webpack这个把多个文件组织其他提供给浏览器处理的框架技术:
      • Webpack使用的就是vue-loader等来组织各种web资源的。

相关文章

  • VUE02:Vue组件

      前后端分离使得前端可以想开发后台一样开发,这种思想指导下的Vue是比较常用框架,这个框架的最大特色是页面组件化...

  • vue02

    vue02 vue生命周期 1.0钩子函数: created -> 实例已经创建 √ beforeComp...

  • VUE02

    v-cloak ref monted Vue.directive()自定义指令 }) Vue.filter过滤器 ...

  • Vue02

    一、文档类指令操作 代码示例: v-text:文本变量 v-once:一次性文本赋值 v-html:html文本变...

  • vue02

    v-if 0 1 2 3 4 5 new Vue({ el:".he", data:{ num:Math.floo...

  • vue02

    spa框架:单页应用 (1个页面)组件:component 把一个复杂的页面拆分成若干个组件,最后再拼成一个完整的...

  • VUE02

    Vue案例: localStorage: localStorage生命周期是永久,这意味着除非用户显示在浏览器提供...

  • vue02

    列表展示: j计数器: vue的MVVM vue的生命周期 mustache v-once v-html v-te...

  • Vue3.0 父子组件传值方法

    父组件.vue 子组件.vue

  • provide inject在vue2和vue3中的使用

    vue2父组件 vue2子组件 vue3父组件 vue3子组件 vue3官方详细使用provide inject地...

网友评论

      本文标题:VUE02:Vue组件

      本文链接:https://www.haomeiwen.com/subject/bypzmctx.html