vue-cli(二):组件的理解&组件的创建与使用&组件传值

90 阅读3分钟
组件
  • 1.组件与模块&组件化与模块化的理解
存在问题:
    1.依赖关系混乱 不好维护
    2.代码复用率不高 

组件的定义:
    实现应用中局部功能代码和资源的集合    

模块:
    1.理解:向外提供特定功能的js 一般就是个js文件
    2.为什么:js文件很多很复杂
    3.作用:复用js 简化js的编写 提高js运行效率

组件:
    1.理解:用来实现局部功能效果的代码集合(html/css/js/image...)
    2.为什么:一个界面的功能很复杂
    3.作用:复用代码,简化项目编码,提高运行效率

模块化:
    当应用中的js都以模块来编写的,那这个应用就是一个模块化的应用

组件化:
    当应用中的功能都是多组件的方式来编写 ,那这个应用就是一个组件化的应用
  • 2.非单文件组件&单文件组件
非单文件组件: 
    一个文件中包含有n个组件
单文件组件:
    一个文件中只有1个组件
  • 3.基本使用
1.创建组件: 
    Vue.extend(options)创建,其中options和new Vue(options)
    template + data
2.注册组件: 2种方式 局部 全局
    // 局部注册 靠new Vue的时候传入components选项
    new Vue({
      el: "#demo",
      components: {
        school,
        student,
      },
    });
    // 全局注册 靠Vue.component('组件名',组件)要写在new Vue之前
    Vue.component("student", student);
3.使用组件: 
    编写组件标签 <school></school>
<div id="demo">
  <school></school>
  <student></student>
</div>
<script type="text/javascript">
  //阻止vue在启动时生成生产提示
  Vue.config.productionTip = false;
  // 创建school组件
  const school = Vue.extend({
    template: `
    <div class="demo">
			<h2>学校名称:{{schoolName}}</h2>
			<h2>学校地址:{{address}}</h2>
      <button @click="click">点击提示学校名</button>
		</div>
    `,
    data() {
      return {
        schoolName: "尚硅谷",
        address: "北京",
      };
    },
    methods: {
      click() {
        alert(this.schoolName);
      },
    },
  });
  // 创建 student组件
  const student = Vue.extend({
    template: `
		<div>
			<h2>学生姓名:{{studentName}}</h2>
			<h2>学生年龄:{{age}}</h2>
		</div>
	`,
    data() {
      return {
        studentName: "小杨",
        age: 18,
      };
    },
  });
  // 注册全局组件
  Vue.component("student", student);
  
  // 注册组件
  new Vue({
    el: "#demo",
    // 局部注册
    components: {
      school,
    },
  });
  //创建Vue实例
  // new Vue({
  //   el: "#demo",
  //   data: {},
  // });
</script>
  • 4.注意点
1.单个单词的组件名:
    school 小写
    School 首字母大写
2.多个单词的组件名: 
    'my-school':demo -> k-case的命名
    'MySchool':demo -> 脚手架模式的时候才行不然会报错
3.组件标签:
    <school></school>
    <school/> 脚手架模式下才行否则会导致后续组件无法渲染
4.简写注册组件
    const school = Vue.extend(options) -> const school = options
  • 5.组件的嵌套
<!-- 准备好一个容器 -->
<div id="demo">
    <!-- 如果不写app就在new Vue里面写 -->
    <app></app>
</div>
<script type="text/javascript">
  //阻止vue在启动时生成生产提示
  Vue.config.productionTip = false;
  // 创建 student组件
  const student = Vue.extend({
    template: `
              <div>
                  <h2>学生姓名:{{studentName}}</h2>
                  <h2>学生年龄:{{age}}</h2>
              </div>
          `,
    data() {
      return {
        studentName: "小杨",
        age: 18,
      };
    },
  });
  // 创建school组件
  const school = Vue.extend({
    template: `
        <div class="demo">
            <h2>学校名称:{{schoolName}}</h2>
            <h2>学校地址:{{address}}</h2>
            <student></student>
        </div>
      `,
    data() {
      return {
        schoolName: "尚硅谷",
        address: "北京",
      };
    },
    // 局部注册给school
    components: {
      student,
    },
  });
  //创建一个app 管理所有组件
  const app = Vue.extend({
    template:`
        <school></school>
    `,
    components: {
      school,
    },
  });
  // 注册全局组件
  // Vue.component("student", student);
  // 注册组件
  new Vue({
    // 容器如果不写标签 就在这写
    // template:`<app></app>`,
    el: "#demo",
    // 局部注册
    components: {
        app,
    },
  });
</script>
单文件组件
  • index.html 容器
  • main.js 大哥 入口文件 vm new Vue({}) 一切的开始
  • App.vue 作为一个汇总
  • School.vue
  • Student.vue
  • 查找文件顺序 index.html -> vue.js -> main.js -> app.vue -> School.vue & Student.vue
index.html 容器 
但是这里引用的文件会报错因为浏览器不能直接执行js 识别不了import
<body>
    <div id="root">
        <!-- 写在main.js的new Vue 的 template里面 就可以不写结构标签了-->
        <!-- <App></App> -->
    </div>
    <script src="../js/vue.js"></script>
    <script src="./main.js"></script>
</body>
</html>
main.js 汇总文件 初始化vm 引入App汇总组件
import App from './App.vue'

// new Vue({
//     el:'#root',
//     components:{App},
// })

new Vue({
    el:'#root',
    template:`<App></App>`,
    components:{App},
})
App.vue 汇总School跟Student
<template>
  <div>
    <School></School>
    <Student></Student>
  </div>
</template>

<script>
// 引入组件
import School from './School'
import Student from './Student'

export default {
    name:'App',
    components:{
        School,
        Student,
    }
}
</script>

<style>

</style>
School.vue
<!-- 别人引入 用import引入 -->
<template>
    <div class="demo">
        <h2>学校名称:{{ name }}</h2>
        <h2>学校地址:{{ address }}</h2>
        <button @click="showName">点我提示学校名</button>
    </div>
</template>

<script>
// 直接暴露组件的配置对象
export default {
    name: 'School',
    data() {
        return {
            name: '尚硅谷',
            address: '北京昌平'
        }
    },
    methods: {
        showName() {
            alert(this.name)
        }
    },
}
</script>

<style>
.demo {
    background-color: orange;
}
</style>
Student.vue
<template>
	<div>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生年龄:{{age}}</h2>
	</div>
</template>

<script>
	 export default {
		name:'Student',
		data(){
			return {
				name:'张三',
				age:18
			}
		}
	}
</script>

ES6模块化 暴露和引用 export & import

// 分别暴露
 export const school = Vue.extend({
     data() {
    return {
             name: '尚硅谷',
             address: '北京昌平'
         }
     },
     methods: {
         showName() {
             alert(this.name)
         }
     },
 })

// 统一暴露
 const school = Vue.extend({
     data() {
         return {
             name: '尚硅谷',
             address: '北京昌平'
         }
     },
     methods: {
         showName() {
             alert(this.name)
         }
     },
 })
 export {school}

// 默认暴露
 const school = Vue.extend({
     data() {
         return {
             name: '尚硅谷',
             address: '北京昌平'
         }
     },
     methods: {
         showName() {
            alert(this.name)
         }
    },
})
export default school

// import xxx from xxx 默认暴露的引用方式
// import {} from xxx 非默认暴露的引用方式 麻烦
props 组件传参
  • 写法(3种接收参数)
1.简单写法
props:['name','age','sex']
2.限制props的数据类型
props:{
    name:String,
    age:Number,
    sex:String
}
3.限制props的数据类型 + 初始化默认值 + 必要性限制
props:{
    name:{
        type:String, // name类型字符串
        required:true // 必要的
    },
    age:{
        type:Number,
        default:99 // 默认值
    },
    sex: {
        type: String,
        required:true
    }
}
  • 代码片段
/*App.vue*/
<template>
  <div>
    <!-- 
         加冒号就是表达式 并且Student组件那边限制了age的类型Number 
         如果不加: 就会提示类型错
         如果不写name 就会提示 misss required 
    -->
    <Student ref="student" name="新名字" sex="新性别" :age="18+1" />
  </div>
</template>
/*School.vue 组件*/
// 3.限制props的数据类型+默认值+必要性限制
props:{
    name:{
        type:String, // name类型字符串
        required:true // 必要的
    },
    age:{
        type:Number,
        default:99 // 默认值
    },
    sex: {
        type: String,
        required:true
    }
}

image.png