美文网首页
Vue基础教程之-组件核心概念(四)

Vue基础教程之-组件核心概念(四)

作者: AC编程 | 来源:发表于2021-05-31 10:03 被阅读0次

    一、模块化

    1.1 为什么需要模块化

    没有模块化的世界:全局变量污染、难以管理的依赖。
    常见的模块化标准:CommonJS(node.js)、AMD(民间)、CMD(民间)、UMD(民间)、ES6 Module(官方)

    1.2 全局变量污染

    新建一个test.js文件,test.html文件,在html中用普通方式引入js代码,代码如下

    var nickname = "AlanChen";
    
    function test(){
        console.log("Hello "+nickname);
    }
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script src="./test.js"></script>
    </body>
    </html>
    

    变量nickname和方法test是全局的,是window全局变量,如下

    全局变量污染
    1.3 模块化方式解决全局变量污染

    html采用模块化的方式引入js文件,<script src="./test.js" type="module"></script>,变量nickname和方法test就不再是全局的了。

    模块化方式解决全局变量污染
    1.4 模块化导出与导入

    我们新建一个hello.js文件,并用 export default导出一个helloWorld函数,在test.jsimport该函数,代码如下

    var helloTitle = "Hello World";
    
    export default function helloWorld(){
        console.log(helloTitle);
    }
    
    
    import helloWorld from "./hello.js"
    
    var nickname = "AlanChen";
    
    function test(){
        console.log("Hello "+nickname);
    }
    
    // 测试
    
    //有导出,可以访问
    helloWorld();
    
    //没有导出,无法访问
    console.log(helloTitle);
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script src="./test.js" type="module"></script>
    </body>
    </html>
    
    模块化导出与导入

    二、组件概念

    一个完整的网页是复杂的,如果将其作为一个整体来进行开发,将会遇到下面的问题:
    1、代码凌乱臃肿
    2、不易协作
    3、难以复用

    Vue推荐使用一种更加精细的控制方案:组件化开发。所谓组件化,即把一个页面中区域功能细分,每一个区域成为一个组件,每个组件包含:
    1、功能(JS代码)
    2、内容(模板代码)
    3、样式(CSS代码)

    三、组件开发

    3.1 创建组件

    组件是根据一个普通的配置对象创建的,所以要开发一个组件,只需要写一个配置对象即可,该配置对象和Vue实例的配置是几乎一样的。

            //组件配置对象
            var MyComp={
                data(){
                    return {
                        // ...
                    }
                },
    
                computed:{
                    // ...
                },
    
                methods:{
                    // ...
                },
    
                template: `...`
            }
    

    值得注意的是,组件配置对象和Vue实例有以下几点差异:
    1、无el
    2、data必须是一个函数,该函数返回的对象作为数据
    3、由于没有el配置,组件的虚拟DOM树必须定义在template或render中

    3.2 注册组件

    注册组件分为两种方式,一种是全局注册,一种是局部注册

    3.2.1 全局注册

    一旦全局注册了一个组件,整个应用中任何地方都可以使用该组件

    全局注册

    全局注册的方式是:

            //参数1:组件名称,将来在模板中使用组件时,会使用该名称
            // 参数2:组件配置对象
            // 该代码运行后,即可在模板中使用组件
            Vue.component("MyComp",MyComp);
    

    在模板中,可以使用组件了

            <MyComp />
            <!--或-->
            <MyComp></MyComp>
    

    但在一些工程化的大型项目中,很多组件都不需要全局使用。比如一个登录组件,只有在登录的相关页面中使用,如果全局注册,将导致构建工具无法优化打包,因此,除非组件特别通用,否则不建议使用全局注册。

    3.2.2 局部注册

    局部注册就是哪里要用到组件,就在哪里注册

    局部注册

    局部注册的方式是,在要使用组件的组件或实例中加入一个配置

            // vm:Vue实例
            var vm = new Vue({   
                el:"#app",  // css选择器
    
                // 注册组件(局部注册)
                components:{
                    Title
                },
    
                template: `<Title></Title>`,
            });
    
    3.3 应用组件

    在模板中使用组件特别简单,把组件名当作html元素名使用即可。但要注意以下几点

    1、组件必须有结束
    组件可以自结束,也可以用结束标记结束,但必须要有结束

    2、组件的命名
    无论你使用哪种方式注册组件,组件的名称需要遵循规范。组件可以使用kebab-case短横线命名法,也可以使用PascalCase大驼峰命名法。下面两种命名均是可以的

    var otherComp = {
        components:{
              "my-comp": myComp, //方式1
              MyComp: myComp //方式2
        }
    }
    

    实际上,使用小驼峰命名法,camelCase也是可以识别的,只不过不符合官方要求的规范。使用PascalCase方式命名还有一个额外的好处,即可以在模板中使用两种组件名。

    四、组件树

    一个组件创建好后,往往会在各种地方使用它。它可能多次出现在Vue实例中,也可能出现在其他组件中。于是就形成了一个组件树。

    组件树

    五、向组件传递数据

    大部分组件要完成自身的功能,都需要一些额外的信息,比如一个头像组件,需要告诉它头像的地址,这就需要在使用组件时向组件传递数据。传递数据的方式有很多中,最常见的一种是使用组件属性component props,和Vue实例一样,使用组件时也会创建组件的实例,而组件的属性会被提取到组件实例中,因此可以在模板中使用。

    首先在组件中申明可以接收哪些属性

    var MyComp = {
        props: ["p1","p2","p3"],
    
       template: `
               <div>
                   {{p1}}, {{p2}}, {{p3}}
               </div>
       `
    }
    

    在使用组件时,向其传递属性

    var OtherComp = {
        componets: {
           MyComp
       },
    
       data(){
             return {
                a:1
             }
       },
    
       template: `
             <my-comp :p1="a"  :p2="2"  p3="3"
      `
    }
    

    注意:在组件中,属性是只读的,绝不可以更改,这叫单向数据流。哲学思想:谁的数据谁负责

    属性不可更改

    六、组件创建、注册、使用、属性传值

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id ="app">
        </div>
        <script src="./vue.min.js" ></script>
        <script>
    
           //1、组件配置对象
            var Title = {
    
                //属性
                props: ["version"],
    
                data(){
                    return {
                        title: "库存管理系统",
                    };
                },
                template: `<h1>{{title}} {{version}}</h1>`,
            }
    
            //2、注册组件(全局注册)
           // Vue.component("Title",Title);
    
    
            // 3、使用组件
            // vm:Vue实例
            var vm = new Vue({   
                el:"#app",  // css选择器
    
                // 2、注册组件(局部注册)
                components:{
                    Title
                },
    
                template: `<Title version="V1.0"></Title>`,
            });
        </script>
    </body>
    </html>
    

    七、库存管理系统 demo

    库存管理系统 demo-004

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id="app"></div>
        <script src="./lib/vue.min.js"></script>
        <script src="./src/main.js" type="module"></script>
    </body>
    </html>
    

    main.js

    import App from "./App.js";
    
    new Vue({
    
        components:{
            App,
        },
    
        // template: `<App />`
    
        // render(h){
        //     return h(App);
        // }
    
        render:(h)=>h(App),
    
    }).$mount("#app");
    

    App.js

    
    import Products from "./components/Products.js";
    
    var template = `
    <div>
        <h1>库存管理系统</h1>
        <Products />
    </div>
    `;
    
    export default{
        components:{
            Products
        },
    
       template,
    };
    

    Products.js

    
    var template = `
    <ul>
        <li v-for="(item,i) in products">
            名称:{{item.name}} 
            <button @click="changeStock(item,item.stock-1)">-</button>
            <span v-if="item.stock>0">{{item.stock}}</span>
            <span v-else>无货</span>
            <button @click="changeStock(item,item.stock+1)">+</button>
    
            <button @click="remove(i)">删除</button>
         </li>
    </ul>
    `;
    
    export default{
        template,
    
        data(){
            return {
                products:[
                    {id:1,name:"iphone",stock:10},
                    {id:2,name:"xiaomi",stock:10},
                    {id:3,name:"huawei",stock:10},
                ],
            }
        },
    
        methods:{
            remove(i){
                this.products.splice(i,1);
            },
            changeStock(product,newStock){
                if(newStock<0){
                    newStock = 0;
                }
                product.stock = newStock;
            }
        },
    }
    

    源码

    源码 003、004

    相关文章

      网友评论

          本文标题:Vue基础教程之-组件核心概念(四)

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