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

一、模块化

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容