vue文件
"组件"是一种封装的思想, 把相关业务逻辑的"js/css/html"都封装到一起, 当需要调用"组件"的时候, 只需要在html中期望的位置插入对应的"标签"即可, 比如封装了一个"switch"组件, 在html中我们只需要使用"switch"标签即可.
<switch v-model:checked="isOnline"/>
这里的v-model:checked
是自定义的"双向数据绑定", 后面的课我们会讲解实现.
到这里大家一定很想知道这个组件是如何实现的, 看之前先了解一个新的文件格式.
vue文件
前面的课程都是基于一个html来写的, 但现在了解了组件封装, 就需要知道如何封装, 首先官方建议每一个组件的代码封装到一个"vue"文件中.
下面就是"switch"组件的代码, 其文件名为"switch.vue", 暂时不需要看懂代码, 本章最后一课会讲解, 暂只需要了解代码结构.
<template>
<span
class="switch"
:class="checked && 'switch--checked'"
@click="onChange"
></span>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
props:{
checked:{
type:Boolean,
default:false
}
},
methods:{
onChange(){
this.$emit('update:checked',!this.checked);
}
}
});
</script>
<style lang="scss" scoped>
.switch {
position: relative;
box-sizing: content-box;
display: inline-block;
height: 22px;
width: 42px;
border-radius: 24px;
background-color: #adb5bd;
transition: background-color 200ms;
vertical-align: middle;
cursor: pointer;
&:after {
content: "";
display: block;
position: absolute;
top: 2px;
left: 2px;
width: 18px;
height: 18px;
transition: all 0.2s ease-in-out;
background-color: #fff;
border-radius: 9px;
box-shadow: 0 2px 4px #00230b33;
}
&--checked {
background-color: #42b883;
&:after {
transform: translate3d(20px, 0, 0);
}
}
}
</style>
很明显可以看到3部分代码: "html/js/css", 不知道你有没有疑问:"vue文件浏览器能运行吗?" 答案是:"不能!"
vite编译器
vue官方提供的vue编译器, 使用非常简单, 其可以把vue代码转成"html/js/css", 这样我们的代码就能在浏览器运行了. 不论是开发阶段, 还是最终代码编译阶段, 他都是我们必须的工具. 下节课会讲开发前环境搭建, 届时会具体介绍vite的使用.
创建/运行项目
新vue项目
在IDEA新建一个vue项目
nodejs(运行环境)
vue的开发/编译工具(vite)是基于nodejs平台的, 所以第一步先安装nodejs,下载地址: Node.js, 安装LST(长期维护)版本即可.
npm
安装完毕后命令行会增加一个包管理工具: npm, 包管理可以理解为通过他可以下载js插件, 后续我们开发用到的JS插件都通过他安装. 查看下版本:
C:\Users\qiye>npm -v
9.3.1
C:\Users\qiye>node -v
v18.14.0
vue3
Project setup
npm install
Compiles and hot-reloads for development
npm run serve
Compiles and minifies for production
npm run build
Lints and fixes files
npm run lint
Customize configuration
See Configuration Reference.
因为npm下载插件的默认源是国外服务器, 为了加速改成国内的, 在命令行输入:
设置npm安装源
npm config set registry https://registry.npmmirror.com
比如安装"axios"(接口请求用的js插件, 后面会用到), 就可以执行:
安装axios
npm i axios -S
这里的-S的意思是保存"安装记录", 这样其他人使用你的项目的时候, 可以直接通过npm i安装所有你安装的包. 安装好的插件会存在于项目根下的"node_modules"文件夹.
package.json
"安装记录"保存在项目根目录下的"package.json"中, 其内容是一个JSON, 其中安装记录就保存在"dependencies"字段中.
准备工作到这里就差不多了, 接下来我们初始化项目.
⭐import
特别需要注意, 从现在开始我们使用js插件不再通过"script"标签, 而是使用import语法, 比如需要引入"axios"插件, 只需要在js代码的头部导入:
import axios from 'axios'
第一个"axios"表示你要是用的axios对象, "from"后面的"axios"是插件的名字, 也就是前面你"npm i" 安装时候的名.
🚀 pnpm
虽然"npm"是官方的包安装工具, 但是其每次下载插件都是从网络重新下载, 如果大家网络不太好, 推荐用"pnpm", 使用方法和"npm"完全一样, 只是命令前面多一个"p", 通过其安装的插件会在本地缓存, 下一次安装其会自动使用已下载的. 通过"npm"就可以安装"pnpm"命令:
npm i -g pnpm
这里的"-g"代表安装到全局, 这样在任何项目下都可以执行"pnpm"了, 比如安装axios:
pnpm i axios -S
同时别忘了把他的安装源也改成国内的:
pnpm config set registry https://registry.npmmirror.com
用vite创建项目
"vite"是vue官方的开发/编译工具, 他把vue文件编译成浏览器识别的js/css/html, 同时他还有一个功能就是"初始化项目".
接下来我们初始化一个新vue3项目, 比如在D盘建立一个www目录, 然后通过命令行进入该目录:
npm init vite your-app
cd yourApp
npm install
npm run dev
安装期间会问你项目名称, 我给我的项目起名"yourApp", 其他选项请按照下图选择.
注意: 本章节并不会使用tyepscript开发, 后面的实战项目代码会使用tyepscript开发, 如果你没学过tyepscript也不要担心, 课程中我会一步步教大家typescript.
创建完毕我们会看到如下项目结构:
项目文件简介
先简单介绍下几个主要文件:
main.ts
入口文件, 在此处初始化vue实例.
import { createApp } from 'vue'
// 根组件
import App from './App.vue'
// 挂载vue实例到id为app的元素
createApp(App).mount('#app')
App.vue
根组件, 串联所有其他vue文件, 一个页面就是由多个vue文件互相嵌套组成的.
在代码中每个组件标签的互相引用形成树形结构, 下面是个例子:
App.vue
<h1>我是根组件</h1>
<child-level-1></children-level-1>
child-level-1.vue
<h1>我是App.vue的子组件</h1>
<child-level-2></child-level-2>
child-level-2.vue
<h1>我是App.vue的孙子组件, child-level-1的子组件</h1>
暂时不用关注代码的完整性, 只要理解2点:
- 组件可以嵌套, 并且可以无限制的嵌套.
- 这种嵌套最终就是个树形结构.
components/HelloWorld.vue
子组件, 一般我们把可复用的组件都放在"components"文件夹, 页面级别的组件我们放在新建的"views"文件夹中(views文件夹需要自己建立).
注意: 组件文件的命名格式使用"开头字母大写的驼峰法"命名.
index.html
根HTML模板, 一般在这里我们只是修改下meta信息和标体, 这里的代码会被vue的所有页面所使用.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vue3-start</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
assets/
资源文件夹, 图片和字体等资源都放在这里.
运行开发模式(npm run dev)
上述准备工作完毕后, 就可以运行项目了:
- 用vscode打开项目文件夹.
- window下按ctrl+~打开控制台(~就是esc下面的按键).
- 在控制台输入"npm run dev".
- 运行看到提示后, 按住ctrl, 用鼠标左键点击提示的网址,就可以在浏览器预览项目了.
热更新
打开页面后, 你随意修改vue代码, 可以发现并不需要刷新页面, 页面自动就可以根据代码的变化而变化, 是不是很神奇.
模板语法
通过标记, 我们可以在html中插入变量.
{{}}
变量分隔符, 标记变量. 注意这种语法只能使用在html标签中间.
<div id="#app">
<h1>{{html}}</h1>
<!-- 生成: <h1>小象</h1> -->
</div>
<script>
Vue.createApp({
data(){
return {html: `小象`}
}
}).mount('#app');
</script>
而且还可以是js表达式
<div id="#app">
<h1>{{list[1]}}</h1>
<!-- 生成: <h1>orange</h1> -->
<h1>{{price*num}}</h1>
<!-- 生成: <h1>90</h1> -->
</div>
<script>
Vue.createApp({
data(){
return {
list:['apple','orange'],
price:10,
num:9,
}
}
}).mount('#app');
</script>
指令
vue封装了常用dom操作, 通过在元素上标记"v-"开头的属性来使用, 这些属性就叫做指令.
v-bind
绑定vue变量和标签属性. 这里注意下"style"和"class"的特殊用法即可.
<div id="#app">
<h1 v-bind:align="align">hi vue</h1>
<!-- 生成: <h1 align="center">hi vue</h1> -->
<h1 v-bind:style="{color:color}">hi vue</h1>
<!-- 生成: <h1 style="color:#f10;">hi vue</h1> -->
<h1 v-bind:class="className">hi vue</h1>
<!-- 生成: <h1 class="red big">hi vue</h1> -->
<h1 v-bind:class="className2">hi vue</h1>
<!-- 生成: <h1 class="red">hi vue</h1> -->
</div>
<script>
Vue.createApp({
data:function{
return {
align:'center',
color:'#f10',
className:['red','big'],
className2:{red:true,big:false},
}
}
}).mount('#app');
</script>
<div> HTML 元素是流内容的通用容器。在没有使用 CSS 进行样式化(例如直接对其应用样式,或者应用了某种布局模型,比如 Flexbox,则不会影响内容或布局。作为一个“纯”的容器,<div>元素本质上不代表任何东西。它被用于组合内容,以便可以使用 class 或 id 属性轻松地进行样式化,例如,使用 lang 属性将文档的一部分标记为另一种语言。
缩写
v-bind:可以缩写成:
<h1 v-bind:align="align">hi vue</h1>
<!-- 等于 -->
<h1 :align="align">hi vue</h1>
v-on
事件绑定. 语法为: v-on:事件名
.
<div id="#app">
<h1 v-on:click="onClick">hi vue</h1>
</div>
<script>
Vue.createApp({
methods:{
onClick(){
alert(1);
}
}
}).mount('#app');
</script>
缩写
v-on:
可以缩写为@
.
<h1 v-on:click="onClick">hi vue</h1>
<!-- 等于 -->
<h1 @click="onClick">hi vue</h1>
v-if
控制是否渲染对应元素.
<div id="#app">
<h1 v-if="isShow">hi vue</h1>
</div>
<script>
Vue.createApp({
data(){
return {
isShow: true,
}
}
}).mount('#app');
</script>
配套的还有"v-else-if"和"v-else":
<h1 v-if="isShow">hi vue</h1>
<h1 v-else>你好</h1>
v-show
通过控制元素的样式"display:none"来控制显示隐藏.
<div id="#app">
<h1 v-show="isShow">hi vue</h1>
</div>
<script>
Vue.createApp({
data(){
return {
isShow: false,
}
}
}).mount('#app');
</script>
运行结果
<h1 style="display:none;">hi vue</h1>
v-for
循环, 注意被循环的元素需要标记key属性, key的值要保证唯一, 初期学习可以让key的值等于循环索引(index).
循环数组
<div id="#app">
<h1 v-for="(item,index) in list" :key="index">{{index}} - {{item}}</h1>
</div>
<script>
Vue.createApp({
data(){
return {
list:['苹果','柿子','香蕉']
}
}
}).mount('#app');
</script>
运行结果
<h1>0 - 苹果</h1>
<h1>1 - 柿子</h1>
<h1>2 - 香蕉</h1>
循环对象
<div id="#app">
<h1 v-for="(value, key) in object" :key="key">{{key}} - {{value}}</h1>k
</div>
<script>
Vue.createApp({
data(){
return {
object:{a:1,b:2,c:3}
}
}
}).mount('#app');
</script>
运行结果
<h1>a - 1</h1>
<h1>b - 2</h1>
<h1>c - 3</h1>
循环数字
做测试数据时候很有用.
<h1 v-for="n in 5" :key="n">{{n}}</h1>
运行结果
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
注意: 第一位数字是1.
v-text
填充元素内的文字.
<div id="#app">
<h1 v-text="text"></h1>
</div>
<script>
Vue.createApp({
data(){
return {
text: `大象`
}
}
}).mount('#app');
</script>
运行结果
h1>大象</h1>
v-html
可以填充任意字符串, "v-text"的内容会转义, 比如"v-text"的内容不能是html标签, "v-htm"l可以
<div id="#app">
<h1 v-html="html"></h1>
</div>
<script>
Vue.createApp({
data(){
return {
html: '<small>小象</small>'
}
}
}).mount('#app');
</script>
运行结果
<h1><small>小象</small></h1>
其他指令
下面几个系统指令暂时不展开讲, 后面会随着课程的深入针对性的带出.
<template>
空标签, 并不会渲染到DOM中, 一般用来包围元素进行批量操作.
<template v-if="isShow">
<h1>呐喊</h1>
<p>鲁迅<p>
</template>
<script>
Vue.createApp({
data(){
return {
isShow: true
}
}
}).mount('#app');
</script>
ES6+基础语法
变量和函数(data & methods)
本文是系列文章, 带你从 0 学习 vue3. 让你快速上手vue
vue 是一个 js 框架, 他用 js 封装了 DOM操作, 所以写 vue 不需要直接操作 DOM, 而只要做 2 件事情:
1建立数据变量, 把DOM 的"样式/属性/内容"等和"变量"进行绑定.
2操作数据变量, 绑定的DOM 样式/属性/内容等会自动根据数据更新.
代码编辑器
在写代码之前安装一下代码编辑器, vscode来自微软, 支持vue和ts的语法提示
引入vue.js
和其他js库一样, 我们可以通过"script"标签引入vue.
<script src="https://unpkg.com/vue@3"></script>
基础结构
下面代码是一个vue的最小项目, 不包含任何逻辑代码.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/vue@3"></script>
<title>开始vue3</title>
</head>
<body>
<div id="app"></div>
<script>
Vue.createApp().mount('#app');
</script>
</body>
</html>
Vue.createApp
是vue的初始化语法, 通过mount
指定的元素, vue会检查元素内部的html元素中的vue模板语法, 这里"#app"的意思是id为app的元素. 下面我们分2步实现让页面显示"hi vue".
总结:
导入vue.js的script 脚本文件
<script src="https://unpkg.com/vue@next"></script>
在页面中声明一个将要被vue所控制的DOM区域,既MVVM中的View
<div id="app">
{{ message }}
</div>
创建vm 实例对象(vue 实例对象)
const hello = {
//指定数据源,既MVVM中的Mode1
data: function()
{
return {
message: 'Hello Vue!'
}}
{
const app =Vue.createApp(hello)
app.mount('#app')//指定当前vue实例要控制页面的哪个区域
内容渲染指令:
字符串模板:
<p>{{url1}}</p>
指令,html渲染:
<p v-html="url1"></p>
<a href="baidu.com">百度</a>
百度
属性绑定指令
<a :href="url1">链接</a>
<input type="text" :placeholder="tishi"><br>
<img :src="url1" :style="{width:w}">
return {
url1:"https://random-picture.vercel.app/api",
tishi:"随机图片",
w:"500px",
}
使用JavaScript表达式
<div id="app">
<p >{{number +10 }}</p>
<p >{{ok ? 1 : 0 }}</p>
<p >{{message.split('').reverse().join('、') }}</p>
<p :id="'list'+id" ></p>
<p>{{user.id}}</p>
number:1,
ok:1,
message:"1234",
id:3,
user:{
id:1,
事件绑定渲染
<p >number:{{number}}</p>
<button v-on:click="add">+10</button>
<button @click="add">+10</button>
<button @click="number+=1">+1</button>
data() {
return {
number:1,
}
},
methods:{
add(){
this.number+=10;
}
}
条件渲染:
<div id="app">
<button @click="flag=!flag">点击</button>
<p v-if="flag">显示</p>
<p v-show="flag">显示</p>
</div>
flag:true,
<p v-if="num>0.5">随机数>0.5</p>
<p v-else>随机数《0.5</p>
<p>{{num}}</p>
<p v-if="dengji=='A'">A</p>
<p v-else-if="dengji=='B'">B</p>
flag:true,
num:Math.random(),
dengji:"A",
列表循环
<div id="app">
元素+索引
<ul>
<li v-for="(user,index) in userlist">
索引{{index}},name={{user.name}}
</li>
</ul>
元素
<ul>
<li v-for="user in userlist">
name={{user.name}}
</li>
</ul>
</div>
userlist:[{id: 1, name: 11},{id: 2, name: 22},{id: 3, name: 33}]
key,保证列表唯一
<div id="app">
<input type="text" v-model="name"><button @click="add">添加</button>
<ul>
<li v-for="(user,index) in userlist">
<input type="checkbox">索引{{index}},name={{user.name}}
</li>
</ul>
</div>
<script>
Vue.createApp({
data() {
return {
userlist:[{id: 1, name: 11},{id: 2, name: 22},{id: 3, name: 33}],
newid:4,
name:"",
}
},
methods: {
add(){
this.userlist.push({id: this.newid, name: this.name})
name=""
}
}
}).mount('#app')
</script>