23-Vue组件化编程-非单文件组件

非单文件组件

一个文件中包含有n个组件

 

非单文件组件的特点

1)模板编写没有提示

2)没有构建过程,无法将ES6转换成ES5

3)不支持组件的CSS

4)真正开发中几乎不用

 

Vue中使用组件的三大步骤

1. 定义组件(也就是创建组件)

2. 注册组件(这里有局部注册和全局注册)

3. 使用组件(编写组件标签)

 

注册组件(局部注册)

靠new Vue的时候传入components选项

<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!--准备好一个容器-->
    <div id="root">
      <!--<h2>学校名称:{{schoolName}}</h2>-->
      <!--<h2>学校名称:{{address}}</h2>-->
      <!--第三步:编写学校组件标签-->
      <xuexiao></xuexiao>
      <hr>
      <!--<h2>学生姓名:{{studentName}}</h2>-->
      <!--<h2>学生年龄:{{age}}</h2>-->
      <!--第三步:编写学生组件标签-->
      <xuesheng></xuesheng>
    </div>

    <script type="text/javascript">
      // 阻止 vue 在启动时生成生产提示
      Vue.config.productionTip = false

      // 第一步:创建school组件
      const school = Vue.extend({
        // 这里需要注意,组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪一个容器
        // el:"#root",

        template:'<div>' +
                '<h2>学校名称:{{schoolName}}</h2>' +
                '<h2>学校名称:{{address}}</h2>' +
                '</div>',

        // 在组件的使用中,data必须使用以下的函数式写法,否则会报错
        data(){
          return {
            schoolName:"东华理工大学",
            address:"江西南昌"
          }
        }
      })

      // 第一步:创建student组件
      const student = Vue.extend({

        template:'<div>' +
                '<h2>学生姓名:{{studentName}}</h2>' +
                '<h2>学生年龄:{{age}}</h2>' +
                '</div>',

        data(){
          return {
            studentName:"马铃薯",
            age:26
          }
        }
      })

      // 创建vm
      new Vue({
        el:"#root",

        // data(){
        //   return{
        //     schoolName:"东华理工大学",
        //     address:"江西南昌",
        //     studentName:"马铃薯",
        //     age:26
        //   }
        // }

        // 第二步:注册组件(局部注册)
        components:{
          xuexiao:school,
          xuesheng:student
        }
      })

    </script>
  </body>
</html>

注册组件(全局注册)

靠Vue.component("组件名",组件)

<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!--准备好一个容器-->
    <div id="root">
      <!--第三步:编写hello组件标签-->
      <hello></hello>
    </div>

    <script type="text/javascript">
      // 阻止 vue 在启动时生成生产提示
      Vue.config.productionTip = false

      // 第一步:创建hello组件
      const hello = Vue.extend({
        // 这里需要注意,组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪一个容器
        // el:"#root",

        template:'<div>' +
                '<h2>你好啊,{{name}}</h2>' +
                '</div>',

        // 在组件的使用中,data必须使用以下的函数式写法,否则会报错
        data(){
          return {
            name:"好久不见!"
          }
        }
      })

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

      // 创建vm
      new Vue({
        el:"#root",
      })

    </script>
  </body>
</html>

组件名的注意事项

一个单词组成:

1)第一种写法(首字母小写):school

2)第二种写法(首字母大写):School

多个单词组成:

1)第一种写法(kebab-case命名):my-school

2)第二种写法(CamelCase命名):MySchool(这里需要Vue脚手架支持)

备注:

1)组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行

2)可以使用name配置项指定组件在开发者工具中呈现的名字

<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>几个注意点</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!--准备好一个容器-->
    <div id="root">
      <h1>{{msg}}</h1>
      <!--第三步:使用组件标签-->
      <!--<School></School>-->
      <my-school></my-school>
    </div>

    <script type="text/javascript">
      // 阻止 vue 在启动时生成生产提示
      Vue.config.productionTip = false

      // 第一步:创建组件
      const school = Vue.extend({
        // 可以使用name配置项,指定组件在开发者工具中呈现的名字
        // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为Malingshu
        name:"malingshu",
        
        template:"<div>" +
                "<h2>学校名称:{{schoolName}}</h2>" +
                "<h2>学校地址:{{address}}</h2>" +
                "</div>",

        data(){
          return{
            schoolName:"东华理工大学",
            address:"江西南昌"
          }
        }
      })

      new Vue({
        el:"#root",
        data(){
          return{
            msg:"欢迎来到马铃薯的学习空间!"
          }
        },
        // 第二步:注册组件(局部注册)
        components:{
          // School:school,
          "my-school":school  // 组件在开发者工具中的名字为 MySchool
        }
      })

    </script>
  </body>
</html>

  

组件标签的注意事项

1)第一种写法:<school></school>

2)第二种写法:< school/> (这里需要Vue脚手架支持)

备注:

不实用脚手架时,<school/>会导致后续组件不能渲染

 

一个简写方式

const school = Vue.extend(options) 可简写为:const school = options

这是因为父组件components引入的时候会自动创建

// 创建组件
const school = Vue.extend({
    // 可以使用name配置项,指定组件在开发者工具中呈现的名字
    // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为Malingshu
    name:"malingshu",
    
    template:"<div>" +
            "<h2>学校名称:{{schoolName}}</h2>" +
            "<h2>学校地址:{{address}}</h2>" +
            "</div>",
    
    data(){
      return{
        schoolName:"东华理工大学",
        address:"江西南昌"
      }
    }
})

// 简写
const school2 = {
    // 可以使用name配置项,指定组件在开发者工具中呈现的名字
    // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为Malingshu
    name:"malingshu",
    
    template:"<div>" +
            "<h2>学校名称:{{schoolName}}</h2>" +
            "<h2>学校地址:{{address}}</h2>" +
            "</div>",
    
    data(){
      return{
        schoolName:"东华理工大学",
        address:"江西南昌"
      }
    }
}

 

组件的嵌套

通常一个应用会以一棵嵌套的组件树的形式来组织

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组件的嵌套</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!--准备好一个容器-->
        <div id="root">
            <!--第三步,使用组件标签-->
            <app></app>
        </div>

        <script type="text/javascript">
            // 阻止 vue 在启动时生成生产提示
            Vue.config.productionTip = false

            // 第一步:创建student组件(子组件)
            // 这里需要注意,子组件一定要先定义创建
            const student = Vue.extend({
                // 可以使用name配置项,指定组件在开发者工具中呈现的名字
                // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为Malingshu
                name:"student",

                template:"<div>" +
                    "<h2>学生名字:{{studentName}}</h2>" +
                    "<h2>学生年龄:{{age}}</h2>"+
                    "</div>",

                data(){
                    return{
                        studentName:"马铃薯",
                        age:"26"
                    }
                }
            })

            // 第一步:创建school组件(父组件)
            const school = Vue.extend({
                // 可以使用name配置项,指定组件在开发者工具中呈现的名字
                // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为Malingshu
                name:"school",

                template:"<div>" +
                    "<h2>学校名称:{{schoolName}}</h2>" +
                    "<h2>学校地址:{{address}}</h2>" +
                    "<student></student>" +
                    "</div>",

                data(){
                    return{
                        schoolName:"东华理工大学",
                        address:"江西南昌"
                    }
                },
                // 注册组件(局部注册)
                components:{
                    student:student
                }
            })

            // 创建hello组件(与school组件平级)
            const hello = Vue.extend({
                template:"<h1>{{msg}}</h1>",

                data(){
                    return{
                        msg:"欢迎来到马铃薯的学习空间!"
                    }
                }
            })

            // 创建app组件(最外层,school与hello的父组件)
            const app = Vue.extend({
                template:"<div>" +
                    "<hello></hello>" +
                    "<school></school>" +
                    "</div>",

                components:{
                    hello:hello,
                    school:school
                }
            })


            // 创建vm
            new Vue({
                el:"#root",
                data(){
                    return{
                        msg:"欢迎来到马铃薯的学习空间!"
                    }
                },
                // 第二步:注册组件(局部注册)
                components:{
                    app:app,
                }
            })

        </script>

    </body>
</html>

 

重点:关于VueComponent

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

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

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

 

关于this指向

1)组件配置中:

data函数、methods中的函数、watch中的函数、computed中的函数,它们中的this均是【VueComponent实例对象】

2)new Vue(options)配置中:

data函数、methods中的函数、watch中的函数、computed中的函数,它们中的this均是【Vue实例对象】

 

我们为了更好的区分VueComponent和Vue,以后将VueComponent的实例对象简称vc(也可称为:组件实例对象),Vue的实例对象简称为vm。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>VueComponent</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!--准备好一个容器-->
        <div id="root">
            <school></school>
            <hello></hello>
        </div>

        <script type="text/javascript">
            // 阻止 vue 在启动时生成生产提示
            Vue.config.productionTip = false

            // 创建school组件
            const school = Vue.extend({
                // 可以使用name配置项,指定组件在开发者工具中呈现的名字
                // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为school
                name:"school",

                template:"<div>" +
                    "<h2>学校名称:{{schoolName}}</h2>" +
                    "<h2>学校地址:{{address}}</h2>" +
                    "<button @click='showName'>点击提示学校名称</button>" +
                    "</div>",

                data(){
                    return{
                        schoolName:"东华理工大学",
                        address:"江西南昌"
                    }
                },
                methods:{
                    showName(){
                        console.log(this) // this指向VueComponent实例对象
                        alert(this.schoolName)
                    }
                }
            })

            // 创建hello组件
            const hello = Vue.extend({
                name:"hello",

                template:"<h2>{{msg}}</h2>",

                data(){
                    return{
                        msg:"你好啊"
                    }
                },
            })

            // 组件的本质是"VueComponent"构建函数
            console.log("@", school)
            console.log("#", hello)

            // 验证,每次调用Vue.extend,返回的都是一个全新的VueComponent!!!
            console.log("第一种方法:", school === hello)  //false

            const vm = new Vue({
                el:"#root",

                components:{
                    school:school,
                    hello:hello
                }
            })

        </script>
    </body>
</html>

也就是说,vm和vc是存在一个重要的内置关系的。

VueComponent.prototype.__proto__ === Vue.prototype

VueComponent的原型对象的原型对象就是Vue的原型对象,让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

扩展:显示原型(prototype)与隐式原型(proto)

函数的prototype属性:在定义函数时自动添加的,默认值时一个空Object对象

对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性

(实例的隐式原型属性,永远指向自己缔造者的原型对象)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>一个重要的内置关系</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <!--准备好一个容器-->
    <div id="root">
      <school></school>
    </div>

    <script type="text/javascript">
      // 阻止 vue 在启动时生成生产提示
      Vue.config.productionTip = false

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

      // 创建school组件
      const school = Vue.extend({
        // 可以使用name配置项,指定组件在开发者工具中呈现的名字
        // 也就是说,只要使用了name配置项,不管注册组件时使用的名字是什么,组件在开发者工具中的名字都为school
        name:"school",

        template:"<div>" +
                "<h2>学校名称:{{schoolName}}</h2>" +
                "<h2>学校地址:{{address}}</h2>" +
                "<button @click='showX'>点击输出x</button>" +
                "</div>",

        data(){
          return{
            schoolName:"东华理工大学",
            address:"江西南昌"
          }
        },
        methods:{
          showX(){
            // 这里的 this 指的是 school组件的实例对象VueComponent实例对象(vc)
            // 内置关系:VueComponent.prototype.__proto__ === Vue.prototype
            console.log(this.__proto__.x)  //99
            console.log(this.x)  //99
          }
        }
      })

      // 创建一个vm
      new Vue({
        el:"#root",
        data(){
          return{
            msg:"你好啊"
          }
        },
        components:{
          school:school
        }
      })

      // console.log(VueComponent.prototype.__proto__ === Vue.prototype) // 报错,这是因为VueComponent是通过Vue.exteng(options)返回给school组件
      console.log(school.prototype.__proto__ === Vue.prototype) // true

      // // 定义一个构造函数
      // function Demo(){
      //   this.a = 1
      //   this.b = 2
      // }
      //
      // // 创建一个Demo的实例对象
      // const d = new Demo()
      //
      // // Demo.prototype 属性,显示原型属性
      // console.log(Demo.prototype)
      // // d.__proto__ 属性,隐式原型属性
      // console.log(d.__proto__)
      //
      // // 程序员通过显示原型属性Demo.prototype,操作原型对象,追加一个x属性,值为99
      // Demo.prototype.x = 99
      // // 通过隐式原型属性d.__proto__,获取原型对象的x属性
      // console.log("@", d.__proto__.x) //@ 99
      // console.log("@", d.x) //@ 99

    </script>
  </body>
</html>

 

 

posted @ 2023-10-14 22:52  马铃薯1  阅读(63)  评论(0编辑  收藏  举报