Vue 笔记二—Vue 组件化编程

发布于 2021-08-04  329 次阅读


什么是组件

file

file

file

1.非单文件组件

基本使用

<div id="root">
    <hello></hello>
    <hr />
    <h1>{{msg}}</h1>
    <hr />
    <!-- 第三步:编写组件标签 -->
    <blog></blog>
    <hr />
    <!-- 第三步:编写组件标签 -->
    <student></student>
</div>
<div id="root2">
    <hello></hello>
</div>

<script type="text/javascript">
    // 第一步:创建 blog 组件
    const blog = Vue.extend({
        // 组件定义时,一定不要写 el 配置项,因为最终所有的组件都要被一个 vm 管理,由 vm 决定服务于哪个容器。
        // el:'#root',
        template: `
                <div class="demo">
                    <h2>博客名称:{{blogName}}</h2>
                    <h2>博客地址:{{address}}</h2>
                    <button @click="showName">点我提示博客名</button>
                </div>
            `,
        data() {
            // 组件方式要写函数式,对象具有引用关系,函数则返回一个新对象,不存在引用关系
            return {
                blogName: "星宿君 の Blog",
                address: "https://blog.huxinfeng.com",
            };
        },
        methods: {
            showName() {
                alert(this.blogName);
            },
        },
    });

    // 第一步:创建 student 组件
    const student = Vue.extend({
        template: `
                <div>
                    <h2>同学姓名:{{studentName}}</h2>
                    <h2>同学年龄:{{age}}</h2>
                </div>
            `,
        data() {
            return {
                studentName: "张三",
                age: 18,
            };
        },
    });

    // 第一步:创建 hello 组件
    const hello = Vue.extend({
        template: `
                <div>
                    <h2>你好啊!{{name}}</h2>
                </div>
            `,
        data() {
            return {
                name: "Tom",
            };
        },
    });

    // 第二步:全局注册组件
    Vue.component("hello", hello);

    // 创建 vm
    new Vue({
        el: "#root",
        data: {
            msg: "你好啊!",
        },
        // 第二步:注册组件(局部注册)
        components: {
            blog,
            student,
        },
    });

    new Vue({
        el: "#root2",
    });
</script>
小结
  1. Vue 中使用组件的三大步骤:
    (1) 定义组件(创建组件)
    (2) 注册组件
    (3) 使用组件(写组件标签)
  2. 如何定义一个组件?
    使用 Vue.extend(options)创建,其中 options 和 new Vue(options)时传入的那个 options 几乎一样,但也有点区别;
    区别如下:
    (1) el 不要写,为什么?
    ——— 最终所有的组件都要经过一个 vm 的管理,由 vm 中的 el 决定服务哪个容器。
    (2) data 必须写成函数,为什么?
    ——— 避免组件被复用时,数据存在引用关系。
    备注:使用 template 可以配置组件结构。
  3. 如何注册组件?
    (1) 局部注册:靠 new Vue 的时候传入 components 选项
    (2) 全局注册:靠 Vue.component('组件名',组件)
  4. 编写组件标签:

几个注意点

<div id="root">
    <h1>{{msg}}</h1>
    <blog></blog>
</div>

<script type="text/javascript">
    // 定义组件
    const s = Vue.extend({
        // 开发者工具栏显示的组件名
        name: "huxinfeng",
        template: `
                <div>
                    <h2>博客名称:{{name}}</h2>
                    <h2>博客地址:{{address}}</h2>
                </div>
            `,
        data() {
            return {
                name: "星宿君 の Blog",
                address: "https://blog.huxinfeng.com",
            };
        },
    });

    new Vue({
        el: "#root",
        data: {
            msg: "欢迎学习Vue!",
        },
        components: {
            blog: s,
        },
    });
</script>
小结

几个注意点:

  1. 关于组件名:
    一个单词组成:
    第一种写法(首字母小写):blog
    第二种写法(首字母大写):Blog
    多个单词组成:
    第一种写法(kebab-case 命名):my-blog
    第二种写法(CamelCase 命名):MyBlog (需要 Vue 脚手架支持)
    备注:
    (1) 组件名尽可能回避 HTML 中已有的元素名称,例如:h2、H2 都不行。
    (2) 可以使用 name 配置项指定组件在开发者工具中呈现的名字。
  2. 关于组件标签:
    第一种写法:
    第二种写法:
    备注:不用使用脚手架时,会导致后续组件不能渲染,即多个只会渲染一个。
  3. 一个简写方式:
    const blog = Vue.extend(options) 可简写为:const blog = options,
    可以在 vue.js 源码,第 243 行,写入一个 debugger;运行之后,很明显调用了该方法,vue 底层在 components 里面进行了判断

组件的嵌套

<div id="root"></div>

<script type="text/javascript">
    // 定义 student 组件
    const student = Vue.extend({
        name: "student",
        template: `
                <div>
                    <h2>同学姓名:{{name}}</h2>
                    <h2>同学年龄:{{age}}</h2>
                </div>
            `,
        data() {
            return {
                name: "星宿君",
                age: 18,
            };
        },
    });

    // 定义 blog 组件
    const blog = Vue.extend({
        name: "blog",
        template: `
                <div>
                    <h2>博客名称:{{name}}</h2>
                    <h2>博客地址:{{address}}</h2>
                    <student></student>
                </div>
            `,
        data() {
            return {
                name: "星宿君 の Blog",
                address: "https://blog.huxinfeng.com",
            };
        },
        // 注册组件(局部)
        components: {
            student,
        },
    });

    // 定义 hello 组件
    const hello = Vue.extend({
        template: `<h1>{{msg}}</h1>`,
        data() {
            return {
                msg: "欢迎来访星宿君 の Blog!",
            };
        },
    });

    // 定义 app 组件
    const app = Vue.extend({
        template: `
                <div>
                    <hello></hello>
                    <blog></blog>
                </div>
            `,
        components: {
            blog,
            hello,
        },
    });

    // 创建 vm
    new Vue({
        el: "#root",
        template: "<app></app>",
        // 注册组件(局部)
        components: { app },
    });
</script>

VueComponent

<div id="root">
    <blog></blog>
    <hello></hello>
</div>

<script type="text/javascript">
    // 定义 blog 组件
    const blog = Vue.extend({
        name: "blog",
        template: `
                <div>
                    <h2>博客名称:{{name}}</h2>
                    <h2>博客地址:{{address}}</h2>
                    <button @click="showName">点我提示博客名</button>
                </div>
            `,
        data() {
            return {
                name: "星宿君 の Blog",
                address: "https://blog.huxinfeng.com",
            };
        },
        methods: {
            showName() {
                console.log("showName", this);
            },
        },
    });

    const test = Vue.extend({
        template: `<span>星宿君</span>`,
    });

    // 定义 hello 组件
    const hello = Vue.extend({
        template: `
                <div>
                    <h2>{{msg}}</h2>
                    <test></test>
                </div>
            `,
        data() {
            return {
                msg: "你好啊!",
            };
        },
        components: { test },
    });

    // console.log('@',blog)
    // console.log('#',hello)

    // 创建 vm
    const vm = new Vue({
        el: "#root",
        components: { blog, hello },
    });
</script>

Vue.extend 源码分析

Vue.extend = function (extendOptions) {
    /* .......... */

    var Sub = function VueComponent(options) {
        this._init(options);
    };

    /* .......... */

    return Sub;
};
小结

关于 VueComponent:

  1. blog 组件本质是一个名为 VueComponent 的构造函数,且不是程序员定义的,是 Vue.extend 生成的。
  2. 我们只需要写,Vue 解析时会帮我们创建 blog 组件的实例对象,
    即 Vue 帮我们执行的:new VueComponent(options)。
  3. 特别注意:每次调用 Vue.extend,返回的都是一个全新的 VueComponent!!!!,见上面 Vue.extend 源码分析
  4. 关于 this 指向:
    (1) 组件配置中:
    data 函数、methods 中的函数、watch 中的函数、computed 中的函数 它们的 this 均是【VueComponent 实例对象】。
    (2) new Vue(options)配置中:
    data 函数、methods 中的函数、watch 中的函数、computed 中的函数 它们的 this 均是【Vue 实例对象】。
  5. VueComponent 的实例对象,以后简称 vc(也可称之为:组件实例对象)。
    Vue 的实例对象,以后简称 vm。

一个重要的内置关系

<div id="root">
    <blog></blog>
</div>

<script type="text/javascript">
    Vue.prototype.x = 99;

    // 定义 blog 组件
    const blog = Vue.extend({
        name: "blog",
        template: `
                <div>
                    <h2>博客名称:{{name}}</h2>
                    <h2>博客地址:{{address}}</h2>
                    <button @click="showX">点我输出x</button>
                </div>
            `,
        data() {
            return {
                name: "星宿君 の Blog",
                address: "https://blog.huxinfeng.com",
            };
        },
        methods: {
            showX() {
                console.log(this.x);
            },
        },
    });

    // 创建一个 vm
    const vm = new Vue({
        el: "#root",
        data: {
            msg: "你好",
        },
        components: { blog },
    });

    // 定义一个构造函数
    /* function Demo(){
            this.a = 1
            this.b = 2
        }
        // 创建一个 Demo 的实例对象
        const d = new Demo()

        console.log(Demo.prototype) // 显示原型属性

        console.log(d.__proto__) // 隐式原型属性

        console.log(Demo.prototype === d.__proto__)

        // 程序员通过显示原型属性操作原型对象,追加一个 x 属性,值为99
        Demo.prototype.x = 99

        console.log('@',d) */
</script>
小结
  1. 一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype
  2. 为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue 原型上的属性、方法。

2.单文件组件


博主好穷啊,快点支助一下吧 ε = = (づ′▽`)づ