18.非单文件组件

99 阅读2分钟

1.基本使用


 <!-- 准备一个容器 -->
<div id="root">
    <hello></hello>
    <h1>{{msg}}</h1>
    <hr>
    <!-- 第三步:编写组件标签 -->
    <school></school>

    <hr>
    <!-- 第三步:编写组件标签 -->
    <student></student>
    <student></student>
</div>
<div id="root2">
    <hello></hello>

</div>
<script>
    // 第一步:创建school组件
    const school = Vue.extend({
       // el: '#root',//组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm的el决定服务哪个容器。
        template: `
        <div>
            <h1>学校名称:{{schoolName}}</h1>
            <h1>学校地址:{{address}}</h1>
            <button @click="showName">点我显示学校名</button>
        </div>    
        `,
        data() {
            return {
                schoolName: '掘金学校',
                address: '中国',
            }
        },
        methods: {
            showName() {
                alert(this.schoolName)
            }
        },
    })
    // 第一步:创建student组件
    const student = Vue.extend({
        template: `
        <div>
            <h1>学生姓名:{{studentName}}</h1>
            <h1>学生性别:{{sex}}</h1>
        </div>    
        `,
        data() {
            return {
                studentName: '张三',
                sex: '男'
            }
        }
    })

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

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


    //创建Vue实例
    new Vue({
        el: '#root',
        data: {
            msg: 'hi',
        },
        //第二步:注册组件(局部注册)
        components: {
            school, student
        }

    })

    new Vue({
        el: '#root2'
    })
</script>

image.png

小结 image.png

2.几个注意点


1).关于组件名

一个单词组成:
image.png

上面两种写法在Vue中第一个字母都是大写
image.png

多个单词组成:
image.png

image.png
上方写法在Vue中显示是这样的
image.png

如果用第二种写法(MySchool),却无Vue脚手架支持 image.png

就会报错 image.png

备注: image.png

用h2作为组件名
image.png

会出现这样的错误 image.png

用H2作为组件名
image.png

不会报错,但组件不会生效,标签直接变为 image.png

image.png

使用name配置项指定组件在开发者工具中呈现的名字 image.png
如下图 image.png

2).关于组件标签 image.png

用第二种写法,不使用脚手架,你写多个标签, image.png
结果却显示一个 image.png

3).一个简写方式 image.png

image.png

这个小结用到的代码

<div id="root">
    <h1>{{welcome}}</h1>
    <!-- <school></school> -->
    <school />
    <school />
    <school />
</div>
<script>
    const s = Vue.extend({
        name: 'juejin',
        template: `
        <div>
            <h1>学校名称:{{schoolName}}</h1>
            <h1>学校地址:{{address}}</h1>
        </div>
        `,
        data() {
            return {
                schoolName: '掘金学校',
                address: '中国',
            }
        }
    })
    new Vue({
        el: '#root',
        data: {
            welcome: '欢迎进入掘金'
        },
        components: {
            school: s
        }
    })
</script>

小结 image.png

3.组件的嵌套


 <div id="root">

</div>
<script>

    //定义student组件
    const student = Vue.extend({
        template: `
        <div>
            <h1>学生姓名:{{studentName}}</h1>
            <h1>学生性别:{{sex}}</h1>
        </div>    
        `,
        data() {
            return {
                studentName: '张三',
                sex: '男'
            }
        }
    })

    //定义一个school组件
    const school = Vue.extend({
        name: 'school',
        template: `
        <div>
            <h1>学校名称:{{schoolName}}</h1>
            <h1>学校地址:{{address}}</h1>
            <student></student>
        </div>
        `,
        data() {
            return {
                schoolName: '掘金学校',
                address: '中国',
            }
        },
        components: {
            student
        }
    })

    //定义一个hello组件
    const hello = Vue.extend({
        template: `
        <div>你好啊!{{name}}</div>
        `,
        data() {
            return {
                name: 'juejing'
            }
        }
    })

    //定义一个app组件
    const app = Vue.extend({
        template: `
        <div>
            <hello></hello>
            <school></school>
        </div>
        `,
        data() {
            return {
                name: 'juejing'
            }
        },
        components: {
            school, hello
        }
    })

    new Vue({
        template: `
        <app></app>
        `,
        el: '#root',
        //注册组件(局部)
        components: {
            app
        }
    })

</script>

image.png

4.Vuecomponent


image.png

1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的

image.png

image.png

image.png

2.我们只需要写《school/》或《school》《/school》,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)

image.png

image.png 即由图可看出VueComputent被调用了两次

3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComputent!!!

在一个school组件上再加一个hello组件 image.png

输出以下内容检验一下
image.png
那么在控制台就会输出 image.png 而且在Vue.js代码中可以看到 image.png

4.关于this指向

image.png

image.png

image.png

5.VueComponent的实例对象,以后就简称vc(也可称之为:组件实例对象)。
   Vue的实例对象,以后简称vm
6.vm管理着许多vc

在hello组件中嵌套一个test组件
image.png
则在控制台可看到vm中的children可以找到vc image.png

#vm和vc很像,就像双胞胎,vc有的vm都有,但vc有的vm不一定有,例如el

本小结《4.Vuecomponent》用到代码如下:

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

<script>
    const school = Vue.extend({
        template: `
        <div>
            <h1>学校名称:{{schoolName}}</h1>
            <h1>学校地址:{{address}}</h1>
            <button @click="showName">点我显示学校名</button>
        </div>    
        `,
        data() {
            return {
                schoolName: '掘金学校',
                address: '中国',
            }
        },
        methods: {
            showName() {
                // alert(this.schoolName)
                console.log('showName', this)
            }
        },
    })

    const test = Vue.extend({
        template: `
        <div>啊!!!</div>
        `
    })

    const hello = Vue.extend({
        template: `
        <div>
           <div>你好啊!{{name}}</div>
           <test></test>
        </div>
        `,
        data() {
            return {
                name: 'juejing'
            }
        },
        components: {
            test
        }
    })

    console.log('@' + school)
    console.log('#' + hello)
    console.log('~' + school === hello)
    hello.a = 99
    console.log('hello的a为' + hello.a)
    console.log('school的a为' + school.a)

    const vm = new Vue({
        el: '#root',
        components: {
            school, hello
        }

    })
</script>

image.png

5.一个重要的内置关系

1.原型对象
 <script>

     //定义一个构造函数
     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>

image.png

2.一个重要的内置关系:VueComponent.prototype.__proto__===Vue.prototype
分析Vue与VueComponent的关系图

image.png

为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法。
 <div id="root">
    <school></school>

</div>

<script>
    Vue.prototype.x = 99

    const school = Vue.extend({
        name: 'school',
        template: `
        <div>
            <h1>学校名称:{{schoolName}}</h1>
            <h1>学校地址:{{address}}</h1>
            <button @click="ShowX">点我输出x</button>
        </div>
        `,
        data() {
            return {
                schoolName: '掘金学校',
                address: '中国',
            }
        },
        methods: {
            ShowX() {
                console.log(this.x)
            }
        },
    })

    new Vue({
        el: '#root',
        data: {
            msg: '你好'

        },
        components: {
            school
        }
    })

    console.log(school.prototype.__proto__ === Vue.prototype)
</script>

image.png