目录
四.脚手架CLI
1.安装
1.安装webpack npm install webpack -g 全局安装 2.安装脚手架 vue cli npm install -g @vue/cli 最新版本的 为什么要全局安装 ,因为这台电脑要经常创建vue的项目 npm install -g @vue/cli@4.5.15 指定版本 vue --version 检测脚手架的版本 【vue -V也可以】 3.使用脚手架创建项目 vue create demo(项目的名称,不能有大写的英文单词)
2.目录结构
public 目录 index.html 单页面应用的页面 (挂载点) static目录 ,里面存放一些第三方文件,不需要经过编译的 niode_modules 目录, 模块目录 src 目录 (95以上的代码都在src中) main.js src核心入口文件,核心文件 App.vue 根组件 components 组件目录 assets 静态资源 是经过webpack编译的
在vue中,所有的组件都是以.vue为结尾的文件,同时一个文件包括三个部分 template模板 script js逻辑 style样式
五.组件通信
1.父传子
在Vue.js 2中,父组件可以通过props属性向子组件传递数据。以下是一个简单的示例,演示了如何在父组件中定义prop,并在子组件中接收和使用它。
父组件 (ParentComponent.vue)
假设我们有一个父组件 ParentComponent.vue
,想要向子组件传递一个名为 message
的prop。
<template>
<div>
<h2>Parent Component</h2>
<ChildComponent :message="parentMessage" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
parentMessage: 'Hello from parent!'
};
}
};
</script>
在这个例子中,父组件通过 :message="parentMessage"
将 parentMessage
数据作为prop传递给子组件。
子组件 (ChildComponent.vue)
子组件需要定义 props
属性来接收父组件传递过来的数据。
<template>
<div>
<h3>Child Component</h3>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
props: {
message: String
}
};
</script>
在子组件中,我们使用 props
对象来定义接收的 message
属性。在模板中,可以直接使用 {{ message }}
来显示父组件传递过来的消息。
解释说明
-
父组件中的props传递:
- 在父组件中,通过
:message="parentMessage"
将parentMessage
数据传递给子组件的message
prop。
- 在父组件中,通过
-
子组件中的props接收:
- 在子组件中,通过
props
对象定义了message
属性,该属性的类型为String
。 - 在子组件的模板中,可以直接使用
{{ message }}
来访问和显示父组件传递过来的数据。
- 在子组件中,通过
这种方式使得父组件和子组件之间能够有效地传递和共享数据,是Vue.js组件间通信的一种常见模式。
2.子传父
在Vue.js 2中,子组件向父组件传递数据通常使用$emit
方法来触发自定义事件。以下是一个示例,演示了如何在子组件中使用$emit
向父组件传递数据。
子组件 (ChildComponent.vue)
在子组件中,我们定义一个按钮,当点击按钮时,触发一个事件并将数据传递给父组件。
<template>
<div>
<button @click="sendDataToParent">Send Data to Parent</button>
</div>
</template>
<script>
export default {
methods: {
sendDataToParent() {
// 在这里触发自定义事件,并传递数据给父组件
this.$emit('childEvent', 'Data from child');
}
}
};
</script>
在子组件中,sendDataToParent
方法使用 $emit
方法来触发名为 childEvent
的自定义事件,并将数据 'Data from child'
作为参数传递给父组件。
父组件 (ParentComponent.vue)
在父组件中,我们监听子组件触发的自定义事件,并处理传递过来的数据。
<template>
<div>
<h2>Parent Component</h2>
<p>Received data from child: {{ receivedData }}</p>
<ChildComponent @childEvent="handleChildData" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
receivedData: ''
};
},
methods: {
handleChildData(data) {
// 处理从子组件接收到的数据
this.receivedData = data;
}
}
};
</script>
3.非父子
在Vue.js 2中,如果你需要在非父子组件之间进行通信,一种常见的方法是使用中央事件总线(Event Bus)。中央事件总线是一个空的 Vue 实例,你可以用它来触发事件和监听事件,从而实现组件之间的通信。
创建中央事件总线
首先,你需要在一个单独的文件中创建一个 Vue 实例,作为中央事件总线。这个实例将用于触发和监听事件。
// EventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
在组件中使用中央事件总线
发送事件
在任何需要发送事件的组件中,你可以使用中央事件总线的 $emit
方法来触发一个事件,并传递需要的数据。
<template>
<button @click="sendDataToEventBus">Send Data via EventBus</button>
</template>
<script>
import { EventBus } from './EventBus.js';
export default {
methods: {
sendDataToEventBus() {
EventBus.$emit('eventName', 'Data to be sent');
}
}
};
</script>
在上面的例子中,当按钮被点击时,调用 sendDataToEventBus
方法,它会使用 EventBus.$emit('eventName', 'Data to be sent')
来触发一个名为 eventName
的事件,并传递 'Data to be sent'
作为参数。
接收事件
在其他组件中,你可以使用中央事件总线的 $on
方法来监听事件,并处理接收到的数据。
<script>
import { EventBus } from './EventBus.js';
export default {
data() {
return {
receivedData: ''
};
},
created() {
EventBus.$on('eventName', this.handleEventData);
},
methods: {
handleEventData(data) {
this.receivedData = data;
console.log('Received data:', this.receivedData);
// 在这里处理接收到的数据
}
},
destroyed() {
// 在组件销毁前解绑事件监听
EventBus.$off('eventName', this.handleEventData);
}
};
</script>
在这个例子中,通过 EventBus.$on('eventName', this.handleEventData)
来监听 eventName
事件。当事件被触发时,handleEventData
方法会被调用,接收到的数据会被存储在 receivedData
中,并在控制台打印出来。
注意事项
- 全局事件:中央事件总线是一个全局对象,所有的组件都可以通过它来进行事件的发送和接收。
- 解绑事件监听:为了避免内存泄漏和不必要的事件监听,通常在组件销毁前要使用
EventBus.$off
方法来解绑事件监听。
使用中央事件总线可以有效地实现非父子组件之间的通信,但要注意不要滥用它,因为它可能导致代码的可维护性变差。在较大的应用中,推荐考虑使用 Vuex 等专门用于状态管理的解决方案来管理组件之间的通信和状态。
六.scoped
在 Vue.js 2 中,通过 <style scoped>
可以为组件的样式添加作用域,这样定义的样式只会影响当前组件,不会泄漏到其他组件中去。这对于确保样式的隔离性和组件化非常有用。
使用方法
- 在单文件组件中使用 scoped 样式
在单文件组件(.vue 文件)的 <style>
标签中添加 scoped
关键字:
<template>
<div class="example">
<p>这是一个带有 scoped 样式的组件</p>
</div>
</template>
<style scoped>
.example {
background-color: lightblue;
padding: 20px;
}
p {
font-size: 18px;
}
</style>
在上述例子中,.example
类的样式和 p
元素的样式都只会在当前组件中生效,不会影响到其他组件。
- scoped 样式的工作原理
Vue.js 在处理带有 scoped
属性的样式时,会自动为每个选择器添加一个唯一的属性,确保样式只应用到当前组件中匹配该属性的元素上。这个属性的格式是类似 data-v-hash
的形式,其中 hash
是根据当前组件的路径和内容生成的。
例如,上面的例子中,Vue.js 会将 p
标签的样式转换成类似这样:
.example[data-v-hash] p {
font-size: 18px;
}
这样就确保了样式只会应用到具有相同 data-v-hash
值的元素上,从而实现了样式的隔离。
注意事项
-
样式作用域:
scoped
样式仅影响当前组件内的元素,但不会影响组件内部的子组件。如果希望样式作用到子组件中,需要在子组件的样式中也使用scoped
。 -
复杂选择器:如果需要通过组合选择器来匹配特定元素,确保选择器仍然在当前组件的范围内有效。
-
动态生成的内容:如果组件内容是通过动态渲染生成的,确保
scoped
样式能够正确地应用到这些内容上。
使用 scoped
样式能够有效地提高组件化开发的灵活性和隔离性,使得样式管理更加清晰和可维护。
七.is使用
条件渲染
条件渲染是根据 Vue 实例的数据来决定是否渲染一个组件。例如,你可以根据一个布尔值来切换不同的组件。
<div id="app">
<button @click="toggleComponent">Toggle Component</button>
<div v-if="showComponent">
<FirstComponent></FirstComponent>
</div>
<div v-else>
<SecondComponent></SecondComponent>
</div>
</div>
<script>
Vue.component('FirstComponent', {
template: '<div>First Component</div>'
});
Vue.component('SecondComponent', {
template: '<div>Second Component</div>'
});
new Vue({
el: '#app',
data: {
showComponent: true
},
methods: {
toggleComponent() {
this.showComponent = !this.showComponent;
}
}
});
</script>
在上面的示例中,当点击按钮时,toggleComponent
方法会切换 showComponent
的值,从而根据其布尔值决定显示哪个组件。
动态组件
动态组件允许你在多个组件之间动态地进行切换,这些组件可以预先定义并通过一个动态的 component
标签进行加载。
<div id="app">
<button @click="currentComponent = 'first'">Show First Component</button>
<button @click="currentComponent = 'second'">Show Second Component</button>
<component :is="currentComponent"></component>
</div>
<script>
Vue.component('FirstComponent', {
template: '<div>First Component</div>'
});
Vue.component('SecondComponent', {
template: '<div>Second Component</div>'
});
new Vue({
el: '#app',
data: {
currentComponent: 'first'
}
});
</script>
在这个示例中,通过给 component
标签动态绑定 :is
属性来指定当前要渲染的组件。点击按钮会修改 currentComponent
的值,从而切换不同的组件。
八.slot插槽
在Vue 2中,使用插槽(slot)可以更灵活地定义组件的内容结构,让父组件可以插入任意内容到子组件中预留的插槽位置。下面是一个简单的示例,演示如何在Vue 2中使用插槽:
<!-- ParentComponent.vue -->
<template>
<div>
<h2>Parent Component</h2>
<ChildComponent>
<h3>Content provided by parent</h3>
<p>This is additional content provided by parent component.</p>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
}
};
</script>
<!-- ChildComponent.vue -->
<template>
<div>
<h3>Child Component</h3>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ChildComponent'
};
</script>
在上面的示例中,ParentComponent
是父组件,ChildComponent
是子组件。子组件中使用了 <slot></slot>
来定义插槽的位置。父组件中将任意内容放在 <ChildComponent>
标签之间,这些内容将被传递到子组件的插槽中,并在子组件中渲染出来。
插槽的使用使得组件更加灵活,父组件可以动态地决定子组件内部的部分内容,从而提高了组件的复用性和可组合性。
九.混入
在 Vue 2 中,混入(Mixin)允许你在多个组件中共享一些相同的选项或者逻辑。混入是一个重用 Vue 组件选项的一种非常强大的方式,特别适用于在多个组件中使用相同的逻辑、生命周期钩子或者其他选项。
下面是一个简单的示例,演示如何在 Vue 2 中使用混入:
<!-- mixin-example.vue -->
<template>
<div>
<p>{{ message }}</p>
<button @click="sayHello">Say Hello</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from mixin!'
};
},
methods: {
sayHello() {
alert('Hello!');
}
}
};
</script>
<!-- ComponentA.vue -->
<template>
<div>
<h2>Component A</h2>
<p>{{ message }}</p>
<button @click="sayHello">Say Hello</button>
</div>
</template>
<script>
import MixinExample from './mixin-example.vue';
export default {
mixins: [MixinExample],
created() {
console.log('Component A created');
}
};
</script>
十.ref
在 Vue 2 中,ref
是用来给子组件或者 DOM 元素注册引用的特殊属性。通过 ref
,你可以在父组件中直接访问子组件或者 DOM 元素的实例或者引用,从而可以直接操作它们的属性和方法。下面是一个简单的案例演示如何在 Vue 2 中使用 ref
:
<!-- ParentComponent.vue -->
<template>
<div>
<h2>Parent Component</h2>
<button @click="logMessage">Log Child Component Message</button>
<ChildComponent ref="childRef"></ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
logMessage() {
// 访问子组件的实例,并调用其方法或访问其属性
this.$refs.childRef.showMessage();
}
}
};
</script>
<!-- ChildComponent.vue -->
<template>
<div>
<h3>Child Component</h3>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from child component!'
};
},
methods: {
showMessage() {
alert(this.message);
}
}
};
</script>
在上面的示例中,ParentComponent.vue
是父组件,ChildComponent.vue
是子组件。在父组件中使用了 ref="childRef"
给子组件注册了一个引用。然后在父组件的 logMessage
方法中,通过 this.$refs.childRef
来访问子组件的实例,进而调用子组件的 showMessage
方法。
注意事项:
ref
可以在任何 Vue 组件中使用,包括原生的 DOM 元素和子组件。- 当使用
ref
引用一个子组件时,this.$refs.childRef
实际上引用的是子组件的 Vue 实例。因此,你可以直接访问子组件的数据和方法。 - 如果需要在
ref
绑定的元素或组件上使用原生 DOM 属性或方法,需要在确保元素渲染完成后再操作,通常可以使用mounted
生命周期钩子或者$nextTick
方法。
使用 ref
可以在需要时让父组件更灵活地操作子组件或者 DOM 元素,但应该谨慎使用以避免过度使用引用导致代码可读性和维护性下降。
十一.keep-alive
当你在 Vue 2 中使用 keep-alive
组件时,它可以帮助你缓存动态组件或者是路由视图,以便在切换时保留它们的状态而不是重新渲染。这在性能优化和用户体验上都有显著的提升。以下是一个详细的案例,展示了如何在 Vue 2 中使用 keep-alive
:
假设我们有两个组件:HomeComponent.vue
和 AboutComponent.vue
,它们分别用于主页和关于页面。
1. 创建组件
首先,我们创建这两个简单的组件。
HomeComponent.vue:
<template>
<div>
<h2>Home Component</h2>
<p>Count: {{ count }}</p>
<button @click="increment">Increment Count</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
};
},
methods: {
increment() {
this.count++;
}
}
};
</script>
AboutComponent.vue:
<template>
<div>
<h2>About Component</h2>
<p>This is the about page.</p>
</div>
</template>
<script>
export default {
// No data or methods needed for this example
};
</script>
2. 使用 keep-alive
现在,我们将这些组件放在一个父组件中,并使用 keep-alive
来缓存它们。
App.vue:
<template>
<div id="app">
<h1>Vue 2 Keep-Alive Example</h1>
<!-- Navigation -->
<button @click="currentComponent = 'HomeComponent'">Go to Home</button>
<button @click="currentComponent = 'AboutComponent'">Go to About</button>
<!-- Dynamic component with keep-alive -->
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</div>
</template>
<script>
import HomeComponent from './components/HomeComponent.vue';
import AboutComponent from './components/AboutComponent.vue';
export default {
name: 'App',
components: {
HomeComponent,
AboutComponent
},
data() {
return {
currentComponent: 'HomeComponent'
};
}
};
</script>
<style>
#app {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 20px;
}
button {
margin: 10px;
}
</style>
3. 解释说明
- App.vue 是主组件,包含了两个按钮用于切换显示
HomeComponent
和AboutComponent
。 - 使用
keep-alive
包裹了动态组件<component :is="currentComponent"></component>
,这使得在切换组件时能够保留它们的状态。 currentComponent
是一个动态的属性,根据用户点击的按钮来决定显示哪个组件。
4. 运行效果
当你点击 "Go to Home" 和 "Go to About" 按钮时,Vue 会渲染对应的组件。使用 keep-alive
可以保留每个组件的状态,比如在 HomeComponent
中点击按钮增加计数器,切换到 AboutComponent
再切回来时,HomeComponent
中的计数器状态依然保留。
这个案例展示了如何使用 keep-alive
来提升 Vue 2 应用的性能和用户体验,特别是在需要频繁切换组件但又需要保持状态的场景下非常有用。