vue-js-学习-9-组件基础
上一级页面:vue-js-学习索引
本系列关注前端部分,根据学习路线图达到学习Vue.js的目的
developer路线图developer-roadmap/translations/chinese at master · kamranahmedse/developer-roadmap
前言
组件基础
不使用构建步骤时
当不使用构建步骤时,一个 Vue 组件以一个包含 Vue 特定选项的 JavaScript 对象来定义:
这里可以联系到vue-js-学习-1-创建第一个vue-js应用中提到过的InnerHtml,下面我贴一下InnerHtml
innerHTML
我们自己创建了一个内联的根组件,没有使用脚手架项目里面的App.vue。
我们自己创建的根组件,没有template。
当根组件没有设置
template
选项时,Vue 将自动使用容器的innerHTML
作为模板。
没有template,那么上面的语句写在哪里呢?Vue提示使用容器的 innerHTML
作为模板。
- 文档:element.innerHTML - Web API 接口参考 | MDN (mozilla.org)
innerHTML
这个概念我理解不到位,以后再补这块吧。
我这里写在./index.html
,
![Pasted image 20230126125143.png](https://webdav-1309345210.file.myqcloud.com/images/Pasted image 20230126125143.png)
一开始文档里的按钮的功能我没有实现,我做了一个类似的
Hello vue
标签后来发现是因为我写了两个相同id的div标签,类似下面这样的操作,这样只有第一个div标签生效
<div id="app">{{ message }}</div> <div id="app"> <button @click="count++">{{ count }}</button> </div>
./index.html
的内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<!-- 引入依赖,因为在未采用构建流程的情况下使用 Vue -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">
<button @click="count++">{{ count }}</button>
<p> {{ message }} </p>
</div>
<!-- 不要有两个相同id的div标签 -->
<!-- <div></div> -->
<script>
const { createApp } = Vue;
createApp({
data() {
return {
message: "Hello Vue!",
count: 0,
};
},
}).mount("#app");
</script>
<!-- 注释掉原来的两行 -->
<!-- <div id="app"></div> -->
<!-- <script type="module" src="/src/main.js"></script> -->
</body>
</html>
把内容加在./index.html
,然后刷新网页。即可看到效果
- vite帮助我们自动重启服务器,你无需关注服务器的问题,直接刷新网页即可
![Pasted image 20230126125206.png](https://webdav-1309345210.file.myqcloud.com/images/Pasted image 20230126125206.png)
template
不使用InnerHtml,也可以使用template
export default {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">
You clicked me {{ count }} times.
</button>`
}
使用组件
这个之前用过了
传递 props
props
写在子组件中,然后通过父组件传值过来。
props
接收到值后,就想访问普通的data内的数据那样访问。
使用 v-bind
来传递动态 prop 值的。当事先不知道要渲染的确切内容时,这一点特别有用。
监听事件$emit
这里用到了$emit
,会用就行。
设计思想如下:
- 子组件上抛一个提醒(专业的说法是抛出一个事件)
- 父组件收到提醒,做对应的事情
类似与发布者和订阅者模式,或者说回调函数,或者说委托。都是类似的思想。
即子模块做完了某件事,然后提醒父模块,父模块收到提醒,做出应对。
通过插槽来分配内容
插槽slot
。
- 父组件想要传递点什么东西给子模块
- 子组件在某个位置预留一个插槽
- 这样父组件传递过来的内容会在插槽处渲染出来
子组件中这样写
<template>
<div class="alert-box">
<strong>This is an Error for Demo Purposes</strong>
<!-- 注意这里是插槽 -->
<slot />
</div>
</template>
动态组件
解析一下这个template
<template>
<div class="demo">
<button
v-for="tab in tabs"
:key="tab"
:class="['tab-button', { active: currentTab === tab }]"
@click="currentTab = tab"
>
{{ tab }}
</button>
<component :is="currentTab" class="tab"></component>
</div>
</template>
:key
是v-for
用到的特殊属性,它帮助v-for
进行循环操作,可以看做类似于索引或者主键来理解。
:class
是这个标签的CSS样式,为tab-button active
表名是这个tab正在被激活,它和没激活的样式不同,没激活为tab-button
。
![Pasted image 20230126232406.png](https://webdav-1309345210.file.myqcloud.com/images/Pasted image 20230126232406.png)
@click="currentTab = tab"
是一个内联函数,意思是点击时执行currentTab = tab
操作,即给currentTab
赋值为tab
:is="currentTab"
表明我在调用组件,组件名是currentTab
的属性值,例如Posts
、Archive
class="tab"
是指定了CSS样式,这里用tab
这种样式。指定外观的。
![Pasted image 20230126232805.png](https://webdav-1309345210.file.myqcloud.com/images/Pasted image 20230126232805.png)
is
attribute
你也可以使用 is
attribute 来创建一般的 HTML 元素。
- 当使用在原生 HTML 元素上时,
is
的值必须加上前缀vue:
才可以被解析为一个 Vue 组件。这一点是必要的,为了避免和原生的自定义内置元素相混淆。
<component :is="…">
当使用 <component :is="…">
来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 <KeepAlive>
组件强制被切换掉的组件仍然保持“存活”的状态。
DOM 模板解析注意事项
在 DOM 中直接书写 Vue 模板,即直接把Vue模板写在HTML文件中。
但要注意,以下几种情况不属于在DOM 中直接书写 Vue 模板
- 单文件组件
*.vue
- 内联模板字符串 (例如
template: '…'
) <script type="text/x-template">
实战项目
vue建议我们接下来去用 Vue 做一些有趣的东西,或者研究一些示例。然后才是深入组件的部分。
这里选择先做一点Demo小项目:springboot-vue-后台管理系统-前端部分
然后做一些炫技的玩具项目:谷粒商城:springboot-gulimall
项目见vue-js-学习索引