Vue---(nexTick,全局功能与局部功能,组件,css相关技术)

47 阅读4分钟

nexTick

学习了生命周期函数以后,会有一个问题:我们在写业务时,总是会考虑一个事情: 现在正在写的业务代码能否操作vm.

因此我们需要一个工具,就是让我们写的代码,无论在哪里写,都希望它是组件加载完了以后才运行,nexTick就能解决这个问题,他会在组件加载完成后再运行

<div id='app'>
			<p>{{msg}}</p>
		</div>
		<script>
			var vm = new Vue({
				el: '#app',
				data: {
					msg:"hello"
				},
				methods: {},
				beforeCreate(){
					// let msg="hello"
					// this.msg=msg
					
					//这个函数的回调函数是在组件加载完了才会执行
					// Vue.nextTick(()=>{
					// 	console.log(this.msg)
					// })
					this.$nextTick(()=>{
						console.log(this.msg)
					})
					
				}
			})
			//学习了生命周期函数以后  会有一个问题:我们在写业务时  总是会考虑一个事情: 现在正在写的业务代码能否操作vm.
			//所以我们需要一个工具  就是让我们写的代码 无论在哪里写  都希望它是组件加载完了以后才运行 
		</script>

image.png

案列:ECharts引入

<style type="text/css">
			.box {
				width: 600px;
				height: 600px;
			}
		</style>
		<div id='app'>
			<!-- style="width:600px;height:600px;" -->
			<div class="box" v-echarts>

			</div>
		</div>
		<script>
			var vm = new Vue({
				el: '#app',
				data: {
					
				},
				methods: {},
				directives: {
					echarts: {
						inserted(el) {
							// console.log(this)
                           Vue.nextTick(()=>{
							   var myChart = echarts.init(el);
							   let options={
							   	title: {
							   		text: 'Referer of a Website',
							   		subtext: 'Fake Data',
							   		left: 'center'
							   	},
							   	tooltip: {
							   		trigger: 'item'
							   	},
							   	legend: {
							   		orient: 'vertical',
							   		left: 'left'
							   	},
							   	series: [{
							   		name: 'Access From',
							   		type: 'pie',
							   		radius: '50%',
							   		data: [{
							   				value: 1048,
							   				name: 'Search Engine'
							   			},
							   			{
							   				value: 735,
							   				name: 'Direct'
							   			},
							   			{
							   				value: 580,
							   				name: 'Email'
							   			},
							   			{
							   				value: 484,
							   				name: 'Union Ads'
							   			},
							   			{
							   				value: 300,
							   				name: 'Video Ads'
							   			}
							   		],
							   		emphasis: {
							   			itemStyle: {
							   				shadowBlur: 10,
							   				shadowOffsetX: 0,
							   				shadowColor: 'rgba(0, 0, 0, 0.5)'
							   			}
							   		}
							   	}]
							   }
							   myChart.setOption(options)
						   })
						}
					}
				}
			})
		</script>
	</body>

image.png

局部功能与全局功能

全局:所有组件共同的功能(指令,过滤器,组件)

			Vue.filter("alltool1",function(str){
				return str+"-alltool1"
			})
			Vue.filter("alltool2",function(str){
				return str+"-alltool1"
			})
			Vue.directive("color",function(el,obj){
				el.style.color=obj.value||"red"
			})
			Vue.component("allbox",{
				template:"<div>6666allbox</div>"			
			})

局部:只有当前组件的功能(指令,过滤器,组件)

	 		var vm = new Vue({
				el: '#app',
				data: {
					msg:"appdata"
				},
				methods: {},
				components: {
					Box1: {
						template: `<div class="box1">
						 <p>{{msg|box1tool}}</p>
						  <p v-color2="'blue'" v-color>{{msg|alltool1}}</p>
						  <Box11></Box11>
						  <allbox/>	
						 </div>`,
						data: function() {
							return {
								msg: "hello"
							}
						},
						methods: {},
						filters: {
							box1tool(str) {
								return str + "box1-filter"
							}
						},
						directives:{
							color2:{
								inserted(el,obj){
									el.style.background=obj.value||"red"
								}
							}
						},
						components:{
							Box11:{
								template:`<div class="box11">
								         <h1>box11</h1>
								 </div>`
								 
							}
						}
					},
					Box2:{
						template:`<div>
						        <h1>{{msg|box1tool}}</h1>
								 <h1>{{msg|alltool1}}</h1>
						</div>`,
						data:function(){
							return {
								msg:"box2data"
							}
						}
					}
				}
			})

案列:

		<style type="text/css">
			.app {
				width: 400px;
				height: 900px;
				background-color: gold;
			}

			.box1 {
				width: 200px;
				height: 200px;
				background-color: darkorange;
				margin: 20px;
			}
			.box11{
				width: 100px;
				height: 50px;
				background-color: hotpink;
				margin: 20px;
			}
		</style>
		<div id='app' class="app">
			<Box1></Box1>
			<Box1></Box1>
			<Box2></Box2>
			<p>{{msg|box1tool}}</p>
			<p v-color2="'blue'" v-color>{{msg|alltool1}}</p>
			<allbox></allbox>
		</div>
		<script>
			//全局:所有组件共同的功能(指令,过滤器,组件) 
			//局部:只有当前组件的功能(指令,过滤器,组件)
			Vue.filter("alltool1",function(str){
				return str+"-alltool1"
			})
			Vue.filter("alltool2",function(str){
				return str+"-alltool1"
			})
			Vue.directive("color",function(el,obj){
				el.style.color=obj.value||"red"
			})
			Vue.component("allbox",{
				template:"<div>6666allbox</div>"			
			})
			var vm = new Vue({
				el: '#app',
				data: {
					msg:"appdata"
				},
				methods: {},
				components: {
					Box1: {
						template: `<div class="box1">
						 <p>{{msg|box1tool}}</p>
						  <p v-color2="'blue'" v-color>{{msg|alltool1}}</p>
						  <Box11></Box11>
						  <allbox/>	
						 </div>`,
						data: function() {
							return {
								msg: "hello"
							}
						},
						methods: {},
						filters: {
							box1tool(str) {
								return str + "box1-filter"
							}
						},
						directives:{
							color2:{
								inserted(el,obj){
									el.style.background=obj.value||"red"
								}
							}
						},
						components:{
							Box11:{
								template:`<div class="box11">
								         <h1>box11</h1>
								 </div>`
								 
							}
						}
					},
					Box2:{
						template:`<div>
						        <h1>{{msg|box1tool}}</h1>
								 <h1>{{msg|alltool1}}</h1>
						</div>`,
						data:function(){
							return {
								msg:"box2data"
							}
						}
					}
				}
			})
		</script>

image.png

组件

组件:组件是可复用的 Vue 实例,主要用于开发中 具有相同特征不同数据的模块 把它集成为一个组件 供重复利用

全局组件

注意点:

组件的属性不能用大写字母

组件的名字可以用驼峰命名法,但是使用的时候必须用连字符

全局注册的组件使用时不能使用单标签(不会报错,但是只能使用一次 多次使用只显示第一个)

注册的组件不要跟系统标签同名

案列:

			Vue.component("allbox",{
				template:"<div>6666allbox</div>"			
			})

局部组件

一个vm实例可以有多个局部组件,但是只能供当前vm实例使用

案列:

                var vm = new Vue({
				el: '#app',
				data: {
					msg:"appdata"
				},
				methods: {},
				components: {
					Box1: {
						template: `<div class="box1">
						 <p>{{msg|box1tool}}</p>
						  <p v-color2="'blue'" v-color>{{msg|alltool1}}</p>
						  <Box11></Box11>
						  <allbox/>	
						 </div>`,
						data: function() {
							return {
								msg: "hello"
							}
						},
						methods: {},
						filters: {
							box1tool(str) {
								return str + "box1-filter"
							}
						},
						directives:{
							color2:{
								inserted(el,obj){
									el.style.background=obj.value||"red"
								}
							}
						},
						components:{
							Box11:{
								template:`<div class="box11">
								         <h1>box11</h1>
								 </div>`
								 
							}
						}
					},
					Box2:{
						template:`<div>
						        <h1>{{msg|box1tool}}</h1>
								 <h1>{{msg|alltool1}}</h1>
						</div>`,
						data:function(){
							return {
								msg:"box2data"
							}
						}
					}
				}
			})

单文件组件

引入: 1.官方脚手架

2.挂载vm对象

3.组件引入并渲染到vm中

4.引入文件时:

4.1 一般使用相对路径 上一级用../ 同级使用./ 下级使用/

4.2 @ 代表src文件夹

技术点:

1.在项目下创建vue.config.js 就是vue的打包配置文件: const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, lintOnSave:false//关闭eslint的严格模式检测 })

2.引入文件时 @代表了src目录的意思 这个@是vue的脚手架集成的basepath 其他框架中没有@不要记混乱了

3.注册的组件名不能跟vue中的和原生DOM的重名,注册的名字是驼峰 使用时就用连字符

4.注册的组件 使用时可以用双标签也可以用单标签: 如果有插槽必须用双标签

5.如果.vue的script注释了 在打包的时候 vue的打包环境 会帮我们把这个文件解析为一个对象 然后给这个对象添加一个template属性 值为解析的template页面模板字符串 也就是说 .vue文件中 可以不要和 但是不能不写

6.style可以写多个

7.每一个组件内部只能有一个根元素 不要在根元素上写v-for 循环超过2次就会出现多个根元素

    <div id="app">
			<nav1 son-proprety="子组件使用时属性传进去的值"></nav1>	
			<content1 img2src="./img/2.png"></content1>
		</div>
		
		<div id="app2">
			<nav1 son-proprety="子组件使用时属性传进去的值2"></nav1>
			<content1 img2src="./img/2.png"></content1>	
		</div>
		<script type="text/javascript">
		   //祖册全局组件
			Vue.component("nav1",{
				data(){return {sondata:"子组件的数据"}},
				template:`<div><h1>{{sondata}}</h1><p>{{sonProprety}}</p></div>`,
				props:["sonProprety"]
			})
			
			
			// let content1={
			// 			data(){return {img1:"./img/1.png"}},
			// 			template:`<div><img :src="img1"/><img :src="img2src"/></div>`,
			// 			props:["img2src"]
			// 		}
			
			
			new Vue({
				el:"#app",
				data:{},
				components:{
					// content1
					//注册局部组件
					content1:{
								data(){return {img1:"./img/1.png"}},
								template:`<div><img :src="img1"/><img :src="img2src"/></div>`,
								props:["img2src"]
							}
				}
			})
			new Vue({
				el:"#app2",
				data:{}				
			})
		</script>

组件的属性

组件的属性:简单声明,详细描述

:

1.不符合属性规则也会渲染到页面上,但是会报错

2.属性可以多传,但是注册了的属性就必须传,不然有可能会在使用时因为取值问题出BUG

3.属性名不要(不是不能)用vue官方或者原生标签已经签名过的名字:比如id class href

3.属性的类型验证只是一种验证提示 不会阻止程序运行

简单声明:

案列:

box.vue

 <template>
	<div>
		<h1>{{boxtitle}}</h1>
		<!-- <h2>{{title}}</h2> -->
		<h2>{{pro}}</h2>
	</div>
</template>

<script>
	export default {
		//注册组件的属性
		props:["pro"],
		data() {
			return {
				boxtitle: "组件自己的数据"
			}
		},
		methods:{
			
		}
	}
</script>

<style>
</style>
   

Goods.vue

  <template>
	<div>
		<p>{{title1}}---{{price}}</p>

	</div>
</template>

<script>
	export default {
		props:["title1","price"]
	}
</script>

<style>
</style>
  

Goods2.vue

    <template>
	<div>
		<p>{{obj1.title}}----------{{obj1.price}}</p>
	</div>
</template>

<script>
	export default {
		props:["obj1"]
	}
</script>

<style>
</style>

Nav1.vue

    <template>
	<div>
		<button>btn</button>
		<button>btn</button>
		<button>btn</button>
		<button>btn</button>
		<button>btn</button>
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

App.vue

    <template>
	<div>
		<Nav1></Nav1>
		<box pro="title"></box>
		<box :pro="title"></box>
		<Goods :title1="arr[0].title" :price="arr[0].price"></Goods>
		<Goods :title1="arr[1].title" :price="arr[1].price"></Goods>
		<Goods title1="水煮肉片" price="12"></Goods>
		<Goods2 :obj1="arr[0]"></Goods2>
		<Goods2 v-for="el in arr" :obj1="el"></Goods2>
	</div>
</template>

<script>
	import Nav1 from "@/components/Nav1.vue"	
	import box from "@/components/box.vue"
	import Goods from "@/components/Goods.vue"
	import Goods2 from "@/components/Goods2.vue"
	export default {
		data() {
			return {
				msg: "hello",
				title:"app组件的数据",
				arr:[{title:"鱼香肉丝",price:18,id:12},
				{title:"鱼香肉丝2",price:181,id:122},
				{title:"鱼香肉丝3",price:183,id:123}
				]
			}
		},
		components:{
			Nav1,
			box,
			Goods,
			Goods2
		}
	}
</script>
<style>
	
</style>

详细描述:

    props: {
	propA: Number,		// 基础的类型检查 (`null` 匹配任何类型)
	propB: [String, Number],	// 多个可能的类型
	propC: {	type: String,
     		 required: true	// 必填的字符串
   	},
	propD: {	type: Number,
      		default: 100	// 带有默认值的数字
    	},
	propE: {	type: Object,	// 带有默认值的对象或者数组填Array
		default: function () {	// 不建议直接填对象(因为对象直接量会一直占用内存),一般使用工厂函数,调用时才创建对象节省资源(面试)
        		return { message: 'hello' }
      		}
    	},
	propF: {
      		validator: function (value) {// 自定义验证函数返回为true就代表数据符合我们规定
			return ['success', 'warning', 'danger'].indexOf(value) !== -1
      		}
    	}
  }

css相关技术

全局样式的写法:

1.在.vue文件中的style中写的样式 打包后就是全局样式

2.写一个css文件 在项目中导入就是全局样式

3.如果全局样式出现了相同的选择器. 就看是哪个最后打包引入项目,哪个的优先级就最高

局部样式/CSS作用域的实现和原理:

在style标签中添加一个scoped,原理就是vue的插件webpack打包时会:把当前组件模板中的每一个元素添加一个相同的哈希值命名的属性名并且为添加了scoped的style中的样式选择器上添加一个属性选择器

vue文件中可以出现多个style标签 凡是添加了scoped属性的,里面的选择器就会被修改 没添加scoped属性的就不会被修改

    <template>
    <div id="count">
        <ul>
            <li>图标</li>
            <li><input type="text">
                <input type="button" value="搜索">
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    name: '',
    data() {
    }
}

</script>
<style   scoped>
#count {
    height: 120px;
    background-color: bisque;

}

ul {
    list-style: none;
    display: flex;
    justify-content: space-around;
}
</style>

image.png