【Vue】深入组件&分析脚手架

目录

一、 分析脚手架

二、 ref属性

1、什么是 ref?

2、为什么要用 ref?

3、怎么用 ref?

注意点(很重要)

一句话总结

三、props配置

一、什么是 props?

二、为什么要用 props?

三、怎么用 props?

3.1 父组件传递 props

四、props注意事项

小tips

四、mixin混合

什么是 mixin?

为什么要用 mixin?

怎么用 mixin?

① 先定义一个 mixin.js 文件

注意⚡️

🔥总结一句话

五、插件

什么是 插件(plugin)?

为什么要用插件?

插件怎么用?

1. 写一个插件

2. 使用插件

⚡注意几个关键点

🔥总之一句话

作用:

六、 scoped样式

为什么使用 scoped 样式?

总结不易~ 本章节对我有很大的收获, 希望对你也是!!!!


一、 分析脚手架

 这里来分析Students.Vue组件的模式, 分为template用来书写HTML的地方,script来书写js, style来引入样式,没有可以不写,但是一个组件里面, 必须要包含template和script

School.Vue组件

<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>

Students.Vue组件

<template>
	<div>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生年龄:{{age}}</h2>
	</div>
</template>

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

App组件:用来引入components文件夹里面的所有小组件

<template>
  <div>
    <img src="./assets/logo.png" alt="logo">
    <School></School>
    <Students></Students>
  </div>
</template>

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

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




<!-- <template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
// 引入一个组件
import HelloWorld from './components/HelloWorld.vue'

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

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style> -->

main.js:是整个文件的入口

引入Vue:

import Vue from 'vue'
// 引入App组件 它是所有组件的父组件
// "module": "dist/vue.runtime.esm.js", 引入的是残缺版的Vue
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,只包含:核心功能;没有模板解析器。
  1.     因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容。

创建Vue实例对象 -- vm

new Vue({
  el: '#app',
  // 下面这行代码一会解释 完成了这个功能: 将App组件放入容器
  // render 渲染
  render: h => h(App),

  // render(createElement) {
  // console.log(typeof createElement) // function 一个函数
  // 作用就是创建元素 编写具体的内容
  //   return createElement('h1', '你好啊')
  // }
})

创建Vue实例对象 -- vm 另一种形式

  el: '#app',
  // 下面这行代码一会解释 完成了这个功能: 将App组件放入容器
  render: h => h(App),
}).$mount('#app')

启动组件:ctrl + ~ 可以打开终端,然后配置Vue环境后输入:

npm run revse

运行后 按ctrl键 鼠标就可以点击该链接了! 

二、 ref属性

1、什么是 ref?

简单来说,ref 是 Vue 提供的一个 API,用来给元素或者子组件绑定一个引用标识,方便我们在代码里直接拿到这个元素或者组件实例。

在 Vue2 中,使用 $refs 获取; 在 Vue3 的 Composition API 中,使用 reftemplate ref 获取。

refs 获得组件实例对象

2、为什么要用 ref?

正常来说,Vue 提倡数据驱动视图,不推荐直接操作 DOM,但在实际开发中,有些场景必须要直接拿到元素或组件,比如:

  • 需要手动聚焦 input 输入框

  • 需要调用子组件的方法

  • 需要直接操作第三方库渲染的 DOM

  • 需要做一些复杂的 DOM 操作(比如动画控制)

这时候就必须用到 ref
总之,当数据驱动搞不定时,ref就是你的后备方案。

3、怎么用 ref?

3.1 给元素绑定 ref

<template>
  <input ref="myInput" />
</template>

<script>
export default {
  mounted() {
    // 页面加载完,拿到 input 元素,直接调用 focus
    this.$refs.myInput.focus();
  }
}
</script>

绑定了 ref="myInput",通过 this.$refs.myInput 拿到对应 DOM。

3.2 给组件绑定 ref

<template>
  <ChildComponent ref="childRef" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  methods: {
    callChildMethod() {
      this.$refs.childRef.someMethod();  // 调用子组件里的方法
    }
  }
}
</script>

绑定了 ref="childRef",通过 this.$refs.childRef 拿到子组件实例。

3.3 Vue3 Composition API 写法

<template>
  <input ref="inputRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue';

const inputRef = ref(null);

onMounted(() => {
  inputRef.value.focus();
});
</script>

Vue3 中,ref 是响应式对象,取元素需要 .value

注意点(很重要)

  1. $refs 只有在 mounted 之后才可以访问到。

    • 在 created 阶段访问是 undefined。

  2. $refs 不是响应式的。

    • 它不会触发视图更新,只是单纯的 DOM 引用。

  3. 不要滥用 ref。

    • 正常场景用数据驱动优先,实在需要才直接操作 DOM。

  4. $refs 是只读的,不能直接修改。

    • 修改元素属性应该通过标准 DOM 方法或者 Vue 的方式来做。

一句话总结

👉 ref就是让你可以在Vue中,直接拿到DOM元素或组件实例的一个快捷通道。

三、props配置

一、什么是 props?

props父组件传递数据到子组件的一种机制。

简单理解就是:

父亲给儿子发东西,儿子通过 props 接收。

在 Vue 中,子组件通过 props 来声明要接收哪些数据。


二、为什么要用 props?

因为 Vue 是一个组件化的框架。
组件和组件之间要互相协作,比如:

  • 父组件传数据给子组件(比如用户名、商品信息)

  • 父组件告诉子组件当前是编辑模式还是查看模式

  • 动态地给子组件配置一些不同的初始参数

props 是实现这一切的官方推荐方式。

如果不用 props,每个组件自己拿自己的一份数据,项目会非常混乱,没法维护。

三、怎么用 props?

3.1 父组件传递 props

<template>
  <ChildComponent :username="parentName" :age="18" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      parentName: '小明'
    }
  }
}
</script>

父组件用 冒号:属性名="数据")绑定数据,传给子组件。

3.2 子组件接收 props

<template>
  <div>
    <p>姓名:{{ username }}</p>
    <p>年龄:{{ age }}</p>
  </div>
</template>

<script>
export default {
  props: {
    username: {
      type: String,    // 指定类型
      required: true   // 必填
    },
    age: {
      type: Number,
      default: 0       // 默认值
    }
  }
}
</script>

子组件通过 props 选项声明接收哪些属性、类型是什么、是否必传、默认值是多少。

3.3 只声明字符串数组也可以(简写方式)

export default {
  props: ['username', 'age']
}

适合简单场景,复杂的(需要类型校验、默认值等)建议用对象写法。

四、props注意事项

  1. props 是单向绑定:父传子,子组件修改自己的 props 会出警告。

  2. 不要直接修改 props:如果要改,应该用 data 创建一个本地副本。

data() {
  return {
    localUsername: this.username
  }
}
  • 可以使用 props 校验,防止父组件传错类型导致出错。

  • 动态传递对象/数组要小心,父组件一改,子组件也会响应变化。

  • camelCase / kebab-case 对应问题

    • js 里是 userName

    • 模板里是 user-name

一句话总结:

props 是父组件给子组件传递数据的官方途径,规范、安全、高效,但要遵守单向数据流,不要直接改它。

父组件:

在 Vue 中:

  • 如果是静态的字符串,可以直接写,不用加 :

  • 如果是动态的表达式/变量,就必须加 :

<Student name="李四" sex="男" :age="18" />
  • name="李四":这是静态的字符串,所以直接写就可以了。

  • sex="男":也是静态字符串,直接写没问题。

  • :age="18":前面加了冒号,因为 18 是数字,不是字符串,如果不加 :,Vue会把它当成字符串 "18",而不是数字 18

<template>
	<div>
		<Student name="李四" sex="男" :age="18"/>
	</div>
</template>

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

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

	export default {
		name:'Student',
		data() {
			console.log(this)
			return {
				msg:'我是一个武汉传媒学院的学生',
				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
			}
		}
	}
属性意义
type指定这个 prop 应该是什么数据类型(防止传错)
required表示这个 prop 必须传,不传控制台会警告
default给 prop 指定一个默认值,如果父组件没传就用它

小tips

  • required 和 default 不会一起用,一般:

    • 必传(required: true)就不用默认值。

    • 有默认值(default)就可以不传。

  • 类型校验只是开发时警告,不会阻止项目运行,所以最好自己传对。

四、mixin混合

什么是 mixin?

mixin 是 Vue 里的混入功能,
简单说:

把多个组件都会用到的代码,提前封装好,统一混进来用。


为什么要用 mixin?

因为有些逻辑重复出现了
如果每个组件都自己重新写一遍,又麻烦又难维护

比如:

  • 每个组件进来都要打印“页面加载了”

  • 每个组件都有一些相同的数据、方法

这时候就应该用 mixin,统一抽取哪里需要就混入


怎么用 mixin?

三步走:


① 先定义一个 mixin.js 文件

export const myMixin = {
  data() {
    return {
      message: 'hello from mixin'
    }
  },
  created() {
    console.log('mixin的created钩子被调用了')
  },
  methods: {
    greet() {
      console.log('mixin的方法greet调用了')
    }
  }
}

② 在组件中引入使用

<script>
import { myMixin } from './mixin'

export default {
  name: 'MyComponent',
  mixins: [myMixin],  // 👈 核心在这里
  created() {
    console.log('组件自己的created钩子被调用了')
  }
}
</script>

③ 运行效果

  • 组件加载的时候,mixin里的 created() 组件自己的 created() 都会执行

  • 组件中可以直接用 mixin里面的 datamethods,好像就是自己写的一样。

注意⚡️

  • 如果 组件和mixin里有同名的钩子函数(比如created)都会执行先执行mixin的,再执行组件自己的

  • 如果 data、methods、computed等名字重复组件优先,即组件自己的会覆盖mixin的

🔥总结一句话

mixin就是为了复用逻辑的,统一写一份,到处能用,减少重复劳动。

当我自己的组件中存在mounted

mounted 是 Vue 组件生命周期的一个钩子函数。
简单说就是:
当这个组件的 DOM 元素已经挂载到页面上了,就会自动执行 mounted 里的代码。

(你可以理解成:页面渲染完了,才可以安全操作 DOM了。)

<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 {
      // msg:'我是一个武汉传媒学院的学生',
      name:'武汉传媒学院',
      address: '湖北武汉' ,
      x:666
    }
  },
  mixins:[hunhe, hunhe2],
  // 对于生命周期钩子 是都要进行处理
  mounted() {
    console.log('雷猴啊!!!')
  }

}
</script>

<template>
  <div>
    <h1>{{ msg }}</h1>
    <h2 @click="showName">学生姓名:{{ name }}</h2>
    <h2>学生性别:{{ sex }}</h2>
  </div>
</template>

<script>
// 引入一个混合 hunhe 就是复用配置
import {hunhe, hunhe2} from '../mixin'
export default {
  name:'Student',
  data() {
    return {
      msg:'我是一个武汉传媒学院的学生',
      name:'张三',
      sex: '男' 
    }
  },
  mixins:[hunhe, hunhe2]

}
</script>

mixin.js也存在的时候:

// eslint-disable-next-line no-unused-vars
// 分别暴露
export const hunhe = {
  methods: {
    showName() {
      alert(this.name)
    }
  },
  mounted() {
    console.log('你好啊')
  }
}

export const hunhe2 = {
  data() {
    return {
      x: 100,
      y: 200
    }
  }
}

如果你用了 mixin
mixin里面也有 mounted,那么:

  • 会先执行 mixin 的 mounted

  • 再执行你组件自己的 mounted

  • 顺序是 mixin优先,组件后执行

五、插件

什么是 插件(plugin)

在 Vue 里,插件就是:
👉 把一些功能封装成一个可以全局使用的小模块
👉 安装一次,整个应用任何地方都能用。

比如全局方法、全局指令、全局组件、Vue原型上挂点工具函数……都可以通过插件做到。

一句话总结

插件就是扩展 Vue 功能的一个模块。


为什么要用插件?

  • 功能独立,方便复用。

  • 项目一大,需要统一管理一些功能(比如统一加日志、弹窗、请求封装等等)。

  • 别人封装好了(比如 VueRouter、Vuex),直接用,省事又稳定。


插件怎么用?

插件一般有两步:

1. 写一个插件

一个 Vue 插件本质上就是一个对象,必须提供一个 install 方法

比如自己写个简单的插件:

// myPlugin.js
export default {
  install(Vue) {
    // 添加全局方法
    Vue.prototype.$hello = function() {
      console.log('你好啊,我是插件扩展的方法')
    }

    // 也可以注册全局组件、全局指令等等
  }
}

2. 使用插件

在入口文件(比如 main.js)里使用 Vue.use() 安装插件:

import Vue from 'vue'
import App from './App.vue'
import myPlugin from './myPlugin'

Vue.use(myPlugin) // 安装插件

new Vue({
  render: h => h(App),
}).$mount('#app')

这样,全局都可以用 this.$hello() 了,比如:

export default {
  mounted() {
    this.$hello() // 控制台打印:你好啊,我是插件扩展的方法
  }
}

⚡注意几个关键点

  • 插件必须暴露 install(Vue) 方法。

  • 在 Vue 实例创建之前就要安装插件。

  • Vue.use() 只能调用一次(Vue自己会做防止重复注册)。


🔥总之一句话

插件就是给 Vue 增加全局功能的一种官方标准写法,用来提高可复用性模块化管理

自定义插件:

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.prototype.hello = ()=>{alert('你好啊')}
	}
}

Vue.prototype:这代表了 Vue 的原型对象。Vue 中的每一个实例都继承自 Vue.prototype,所以我们可以在这里添加一些方法或者属性,这样每个实例(即每个 Vue 组件)都可以通过 this 访问到这些方法或属性。

作用:

  1. 全局可用:通过 Vue.prototype,添加的方法可以在所有 Vue 实例中使用。这意味着你在任何一个组件中都可以直接通过 this.hello() 来调用 alert('你好啊'),无论是 Vue 组件、根实例还是子组件。

  2. 访问方式:在 Vue 的组件中,可以像访问 this 上的任何其他方法一样,直接使用 this.hello(),因为 hello 被添加到了 Vue 实例的原型上。

main.js 引入插件:

import Vue from 'vue'

import App from './App.vue'

// 引入插件
import plugins from './plugins'

// 关闭Vue生产提示
Vue.config.productionTip = false

// 插件的本质就是一个对象{} 里面还必须包含一个方法 insrall安装
// 应用(使用)插件
Vue.use(plugins, 1, 2, 3)

// 创建vm
new Vue({
  el: '#app',
  render: h => h(App)
})

六、 scoped样式

scoped 样式是 Vue 中的一种样式机制,用于将样式限制在当前组件内,而不会影响到其他组件。这意味着在 Vue 单文件组件中,<style scoped> 标签内的样式只会作用于当前组件的元素,不会影响到全局或其他组件的元素。

为什么使用 scoped 样式?

在开发大型应用时,我们通常希望每个组件的样式是隔离的,不会相互影响。为了实现这一目标,Vue 提供了 scoped 关键字,用来避免样式冲突。

School局部的

<!-- scoped 局部的 -->
<style scoped>
  .demo {
    background-color: skyblue;
  }

</style>

scoped 在App里面使用 也只是在APP里面能够用 

Student局部的

<style scoped>
  .demo {
    background-color: orange;
  }
</style>

总结不易~ 本章节对我有很大的收获, 希望对你也是!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值