Vue(八)

本文详细介绍了Vue.js中的组件系统,包括Vue实例与组件实例的区别,单文件组件的结构和使用,以及Vue脚手架的创建和配置。此外,还讨论了render函数、props配置、mixin混入机制和插件的使用。最后,提到了scoped样式的概念,用于实现组件的局部样式隔离。
摘要由CSDN通过智能技术生成

目录

1. 组件续

1.1 Vue实例对象(vm)与组件实例对象(vc)

1.2 一个重要的内置关系

1.3 单文件组件

2. Vue脚手架

2.1 创建Vue脚手架

2.2 分析脚手架结构

2.3 render函数

2.4 修改默认配置

3. ref属性

4. props配置

5. mixin混入

6. 插件

7. scoped样式(给Vue添加样式)


1. 组件续

1.1 Vue实例对象(vm)与组件实例对象(vc)

vc有的功能vm都有,但是vm中的el(通过el决定为哪个容器服务),vc不行

每次都返回新的对象,互不影响,改了这个另一个不变  

1.2 一个重要的内置关系

vc/vm都是实例,eg:vue和vm是俩东西

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>一个重要的内置关系</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
   如果没有上面那条线,vue原型上的东西只有vm能用
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
		-->
		<!-- 准备好一个容器-->
		<div id="root">
			<school></school>
		</div>
	</body>

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

		//定义school组件
		const school = Vue.extend({
			name:'school',
			template:`
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
					<button @click="showX">点我输出x</button>
				</div>
			`,
			data(){
				return {
					name:'尚硅谷',
					address:'北京'
				}
			},
			methods: {
				showX(){
					//this是vc
					console.log(this.x)
				}
			},
		})

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

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

1.3 单文件组件

单文件组件后缀都是xxxx.vue结尾

暴露方法一:前面加export

 二:统一暴露

三:默认暴露,用这个

 

 用默认暴露引入的时候简单第一种,剩下的用第二种麻烦

//第一个组件School.vue
<!-- 这是一个组件 包含html,css,script,注意三个标签-->
<template>
<!-- 组件的结构 -->
	<div class="demo">
		<h2>学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
		<button @click="showName">点我提示学校名</button>	
	</div>
</template>

<script>
// 组件交互相关的代码(数据,方法等)原来的data,mathod都算
//别人引入这个模块用import,所以这里头得暴露出去
	 export default {
		//把vue.extend省略了,里面的名字最好和外面的文件名保持一致
		name:'School',
		//这个name是组件名
		data(){
			return {
				//这个name就是个数据
				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>
//把上面两个组件全部放入app组件里
<template>
	<div>
		<School></School>
		<Student></Student>
	</div>
</template>

<script>
	//引入组件
	  //引入school组件从当前目录下
	import School from './School.vue'
	import Student from './Student.vue'

	export default {
		//app汇总所有的组件
		name:'App',
		components:{
			School,
			Student
		}
	}
</script>


<!--输入一个<v就能直接显示下面的
	 <template>
  
</template>

<script>
export default {

}
</script>

<style>

</style> -->
import App from './App.vue'

new Vue({
	el:'#root',
	template:`<App></App>`,
	components:{App},
})
//从这里创建vue实例对象
//在这定义容器
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>练习一下单文件组件的语法</title>
	</head>
	<body>
		<!-- 准备一个容器 -->
		<div id="root"></div>
		<!-- 下面的引入得在容器定义完了以后引入 -->
		<!-- <script type="text/javascript" src="../js/vue.js"></script> -->
		<!-- <script type="text/javascript" src="./main.js"></script> -->
	</body>
</html>

2. Vue脚手架

2.1 创建Vue脚手架

官网:生态系统——Vue.cli

具体步骤:

安装@vue/cli以后创建脚手架直接vue就行

 可以先执行一次备注1,再安装

2.2 分析脚手架结构

执行步骤:先在终端运行 npm run serve,找到main.js,发现里面引入了App组件(创建),从app组件中发现引入了school/student组件,一起执行了(执行结果汇总到app里面)。

app里面最后创建实例通过render把app组件放入容器中(index.html中)

 

/* 
	该文件是整个项目的入口文件main.js
*/
//引入Vue
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false

/* 
	关于不同版本的Vue:
	
		1.vue.js与vue.runtime.xxx.js的区别:
				(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
				(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

		2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
			render函数接收到的createElement函数去指定具体内容。
*/

//创建Vue实例对象---vm
new Vue({
	el:'#app',
	//render函数完成了这个功能:将App组件放入容器中
  render: h => h(App),
	// render:q=> q('h1','你好啊')

	// template:`<h1>你好啊</h1>`,
	// components:{App},
})
//main里出现app,就要写app组件
<!-- 把前面一节写的单文件组件放进脚手架执行 -->
<template>
	<div>
		<img src="./assets/logo.png" alt="logo">
		<School></School>
		<Student></Student>
	</div>
</template>

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

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

school/student组件就是前面单文件的

<!-- 单页面,整个脚手架的 -->统一的html,最后写的app容器
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <!-- 下面注释匹配下面 -->
		<!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
		<!-- 开启移动端的理想视口 -->
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
		<!-- 配置页签图标 -->
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
		<!-- 引入第三方样式 -->
		<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
		<!-- 配置网页标题 -->
    <title>硅谷系统</title>
  </head>
  <body>
		<!-- 当浏览器不支持js时noscript中的元素就会被渲染 -->
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
		<!-- 容器 -->
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

2.3 render函数

代码在main.js的vm里,由于配置简化版vue,无法直接用template没人给解析,用render

(不影响标签的调用,vue提供专门解析.vue文件里的template)

render是个函数, vue帮你调,传入createElement函数,创建具体元素,编写具体内容

写成箭头函数,简写,h1是html里面的内置元素

 

所以下面这个,App一个参数,因为所有内容都在App组件里配置着

 

 不加引号是变量,加了引号变成html结构了

 一般用的是简化版的vue,不带模板解析器,占内存小,用render引入模板解析器

2.4 修改默认配置

 

 红色框里不要随便改,改了就不认了

调整脚手架工作模式 

这个只是调节配置的

 

 vue.config.js里写,比较方便

关于脚手架的一些总结: 

## 脚手架文件结构

	├── node_modules 
	├── public
	│   ├── favicon.ico: 页签图标
	│   └── index.html: 主页面
	├── src
	│   ├── assets: 存放静态资源
	│   │   └── logo.png
	│   │── component: 存放组件
	│   │   └── HelloWorld.vue
	│   │── App.vue: 汇总所有组件
	│   │── main.js: 入口文件
	├── .gitignore: git版本管制忽略的配置
	├── babel.config.js: babel的配置文件
	├── package.json: 应用包配置文件 
	├── README.md: 应用描述文件
	├── package-lock.json:包版本控制文件

## 关于不同版本的Vue

1. vue.js与vue.runtime.xxx.js的区别:
    1. vue.js是完整版的Vue,包含:核心功能 + 模板解析器。
    2. vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
2. 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。

## vue.config.js配置文件

1. 使用vue inspect > output.js可以查看到Vue脚手架的默认配置。
2. 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

3. ref属性

## ref属性

1. 被用来给元素或子组件注册引用信息(id的替代者)
2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上获取的是组件实例对象(vc)
3. 使用方式:
    1. 打标识:```<h1 ref="xxx">.....</h1>``` 或 ```<School ref="xxx"></School>```
    2. 获取:```this.$refs.xxx```
//App.vue,其余的跟前面一样,详见代码
<template>
	<div>
		<h1 v-text="msg" ref="title"></h1>
		<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
		<School ref="sch"/>
		<!-- 给组件加了ref -->
	</div>
</template>

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

	export default {
		name:'App',
		components:{School},
		data() {
			return {
				msg:'欢迎学习Vue!'
			}
		},
		methods: {
			showDOM(){
				//this是vc
		//给哪个元素加了ref,ref就收集哪个元素的信息
				console.log(this.$refs.title) //真实DOM元素
				console.log(this.$refs.btn) //真实DOM元素
				console.log(this.$refs.sch) //拿到School组件的实例对象(vc)
			}
		},
	}
</script>

4. props配置

1.接收到的props值是不允许改的

2. data(定义相同)和props(传进来的)相同,props优先级更高,先执行props里的再执行data里,这样data里就能拿到props的数据

## props配置项

1. 功能:让组件接收外部传过来的数据

2. 传递数据:```<Demo name="xxx"/>```组件标签里面直接传
<!-- 见2,App.vue -->

3. 接收数据:

    1. 第一种方式(只接收):```props:['name'] ```

    2. 第二种方式(限制类型):```props:{name:String}```

    3. 第三种方式(限制类型、限制必要性、指定默认值):

        ```js
        props:{
        	name:{
        	type:String, //类型
        	required:true, //必要性
        	default:'老王' //默认值
        	}
        }
        ```

    > 备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
//3. ref的App.vue
<template>
	<div>
		<Student name="李四" sex="女" :age="18"/>
<!-- 不加v-bind直接给你字符串拼接,加了v-bind引号里的东西算表达式 -->
		<!-- 这块传了数据,在student.vue里面也得定义接收props -->
	</div>
</template>

<script>
	import Student from './components/Student'

	export default {
		name:'App',
		components:{Student}
	}
</script>
//Student.vue
<template>
	<div>
		<h1>{{msg}}</h1>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>学生年龄:{{myAge+1}}</h2>
		<button @click="updateAge">尝试修改收到的年龄</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		data() {
			console.log(this)
			return {
				msg:'我是一个尚硅谷的学生',
	//如果必须要将传入的值改了,就像下面这么在data里定义个
				myAge:this.age
			}
		},
		methods: {
			updateAge(){
				this.myAge++
			}
		},

//三种接收方法
		//简单声明接收
		// props:['name','age','sex'] 

		//接收的同时对数据进行类型限制
		/* props:{
			name:String,
			age:Number,
			sex:String
		} */

		//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
		props:{
			//名字必须得传
			name:{
				type:String, //name的类型是字符串
				required:true, //name是必要的
			},
			age:{
				type:Number,
				default:99 //不传就默认值
			},
			sex:{
				type:String,
				required:true
			}
		}
	}
	//一般required(必要)和default(默认)不会同时出现
</script>

5. mixin混入

两个组件共享一个配置,且两个组件需求得是一样的,复用配置

不破坏原本代码,原来得和混合里冲突用原来的(data和methods中的,生命周期钩子不以任何人为主,两个里面都有都要)

 

全局混入时像这种会出现4遍,整个应用里面所有的vc/vm都会得到

//School.vue
<template>
	<div>
		<h2 @click="showName">学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
	</div>
</template>

<script>
	//引入一个hunhe
	// import {hunhe,hunhe2} from '../mixin'

	export default {
		name:'School',
		data() {
			return {
				name:'尚硅谷',
				address:'北京',
				x:666
			}
		},
		// mixins:[hunhe,hunhe2],
	}
</script>
//Student.vue
<template>
	<div>
		<h2 @click="showName">学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
	</div>
</template>

<script>
//引入混合,分段暴露得加{}
	// import {hunhe,hunhe2} from '../mixin'

	export default {
		name:'Student',
		data() {
			return {
				name:'张三',
				sex:'男'
			}
		},
//应用混合mixins意味着可以配置多个混合
		// mixins:[hunhe,hunhe2]
	}
</script>
//App.vue
<template>
	<div>
		<School/>
		<hr>
		<Student/>
	</div>
</template>

<script>
	import School from './components/School'
	import Student from './components/Student'

	export default {
		name:'App',
		components:{School,Student}
	}
</script>
//main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
import {hunhe,hunhe2} from './mixin'
//关闭Vue的生产提示
Vue.config.productionTip = false

//全局混合,在整个应用里面所有的vc/vm都会得到
Vue.mixin(hunhe)
Vue.mixin(hunhe2)


//创建vm
new Vue({
	el:'#app',
	render: h => h(App)
})
//mixin.js
export const hunhe = {
	methods: {
		showName(){
			alert(this.name)
		}
	},
	mounted() {
		console.log('你好啊!')
	},
}
export const hunhe2 = {
	data() {
		return {
			x:100,
			y:200
		}
	},
}
//分别暴露

6. 插件

本质上是一个对象,但是里面必须包括install方法

## 插件

1. 功能:用于增强Vue

2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

3. 定义插件:

    ```js
    对象.install = function (Vue, options) {
        // 1. 添加全局过滤器
        Vue.filter(....)
    
        // 2. 添加全局指令
        Vue.directive(....)
    
        // 3. 配置全局混入(合)
        Vue.mixin(....)
    
        // 4. 添加实例方法
        Vue.prototype.$myMethod = function () {...}
        Vue.prototype.$myProperty = xxxx
    }
    ```

4. 使用插件:```Vue.use()```
//plugins.js插件
//插件可以提供很多强大的功能,只需要在main.js里引入插件、use一下
//Vue.use(plugins)括号里是插件名
export default {
	install(Vue,x,y,z){
		console.log(x,y,z)
		//全局过滤器
		Vue.filter('mySlice',function(value){
			return value.slice(0,4)
		})

		//定义全局指令
		Vue.directive('fbind',{
			//指令与元素成功绑定时(一上来)
			bind(element,binding){
				element.value = binding.value
			},
			//指令所在元素被插入页面时
			inserted(element,binding){
				element.focus()
			},
			//指令所在的模板被重新解析时
			update(element,binding){
				element.value = binding.value
			}
		})

		//定义混入
		Vue.mixin({
			data() {
				return {
					x:100,
					y:200
				}
			},
		})

		//给Vue原型上添加一个方法(vm和vc就都能用了)
//vue原型上的方法vc/vm都能用		
		Vue.prototype.hello = ()=>{alert('你好啊')}
	}
}
//main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import plugins from './plugins'
//关闭Vue的生产提示
Vue.config.productionTip = false

//应用(使用)插件
Vue.use(plugins,1,2,3)
//允许你往后面带参数,插件可以收到
//创建vm
new Vue({
	el:'#app',
	render: h => h(App)
})

7. scoped样式(给Vue添加样式)

## scoped样式

1. 作用:让样式在局部生效,防止冲突。
2. 写法:```<style scoped>```
//School.js  Student不复制了,就是里面也有个demo class
<template>
	<div class="demo">
		<h2 class="title">学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
	</div>
</template>

<script>
	export default {
		name:'School',
		data() {
			return {
				name:'尚硅谷atguigu',
				address:'北京',
			}
		}
	}
</script>

<style scoped>
/* 这两个组件里都是demo,谁后引入得inport(在app里)就听谁的后来者居上 */
/* 解决:<style scoped>加了以后就表示这些样式只负责本组件模板区域 */
.demo{
		background-color: skyblue;
	}
</style>
//App.js
<template>
	<div>
		<h1 class="title">你好啊</h1>
		<School/>
		<Student/>
	</div>
</template>

<script>
	import Student from './components/Student'
	import School from './components/School'

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

<!-- 一般来说,app里写样式了意味着很多组件都能用,但是加了scoped
就表示只能在app组件里用,所以app组件里一般不用加scoped-->
<style scoped>
	.title{
		color: red;
	}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值