指令修饰符
<!DOCTYPE html>
<html lang="zh - CN">
<head>
<meta charset="UTF - 8">
<title>指令修饰符</title>
</head>
<body>
<!--
指令修饰符
通过 "." 指明一些指令后缀,不同 后缀 封装了不同的处理操作 → 简化代码
① 按键修饰符
@keyup.enter → 键盘回车监听
② v-model修饰符
v-model.trim → 去除首尾空格
v-model.number → 转数字
③ 事件修饰符
@事件名.stop → 阻止冒泡
@事件名.prevent → 阻止默认行为
-->
<div id="app">
<h3>@keyup.enter → 监听键盘回车事件</h3>
<!-- @keyup.enter 相当于判断e.key === 'Enter' -->
<input @keyup.enter="fn" v-model="username" type="text">
<h3>v - model修饰符 .trim .number</h3>
姓名:<input v-model.trim="username" type="text"><br>
年纪:<input v-model.number="age" type="text"><br>
<h3>@事件名.stop → 阻止冒泡</h3>
<div @click="fatherFn" class="father">
<div @click.stop="sonFn" class="son">儿子</div>
</div>
<h3>@事件名.prevent → 阻止默认行为</h3>
<a @click.prevent href="http://www.baidu.com">阻止默认行为</a>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
username: '',
age: ''
},
methods: {
fn (e) {
// if(e.key === 'Enter') {
// console.log('键盘回车的时候触发', this.username)
// }
console.log('键盘回车的时候触发', this.username)
},
fatherFn() {
alert('老父亲被点击了')
},
sonFn(e) {
e.stopPropagation()
alert('儿子被点击了')
}
}
})
</script>
</body>
</html>
v-bind操作class
<!DOCTYPE html>
<html lang="zh - CN">
<head>
<meta charset="UTF - 8">
<title>v-bind操作class</title>
<style>
.box {
width: 200px;
height: 200px;
border: 3px solid #000;
font-size: 30px;
margin-top: 10px;
}
.pink {
background-color: pink;
}
.big {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<!--
v-bind对于样式控制的增强
为了方便开发者进行样式控制,Vue扩展了v-bind的语法,可以针对class类名和style行内样式进行控制
v-bind对于样式控制的增强 - 操作class
语法 :class = "对象/数组"
① 对象 → 键就是类名,值是布尔值。如果值为 true,有这个类,否则没有这个类
<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>
适用场景:一个类名,来回切换
② 数组 → 数组中所有的类,都会添加到盒子上,本质就是一个 class 列表
<div class="box" :class="[ '类名1', '类名2', '类名3' ]"></div>
适用场景:批量添加或删除类
-->
<div id="app">
<div class="box" :class="{ pink: true, big: true }">黑马程序员</div>
<div class="box" :class="['pink', 'big']">黑马程序员</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
v-bind操作style
<!DOCTYPE html>
<html lang="zh - CN">
<head>
<meta charset="UTF - 8">
<title>v-bind操作style</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<!--
v-bind 对于样式控制的增强 - 操作style
语法 :style="样式对象"
<div class="box" :style="{ css属性名1: 'css属性值', css属性名2: 'css属性值' }"></div>
适用场景:某个具体属性的动态设置
-->
<div id="app">
<div class="box" :style="{ width: '400px', height: '400px', backgroundColor: 'green' }"></div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
v-model应用于其他表单元素
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>v-model应用于其他表单元素</title>
</head>
<body>
<!--
v-model 应用于其他表单元素
常见的表单元素都可以用 v-model 绑定关联 → 快速 获取 或 设置 表单元素的值
它会根据 控件类型 自动选取 正确的方法 来更新元素
输入框 input:text → value
文本域 textarea → value
复选框 input:checkbox → checked
单选框 input:radio → checked
下拉菜单 select → value
-->
<div id="app">
<h3>小黑学习网</h3>
姓名:
<input type="text" v-model="username">
<br><br>
是否单身:
<input type="checkbox" v-model="isSingle">
<br><br>
<!--
前置理解:
1.name:给单选框加上 name 属性 可以分组 → 同一组互相会互斥
2.value:给单选框加上 value 属性,用于提交给后台的数据
结合 Vue 使用 → v-model
-->
性别:
<input v-model="gender" type="radio" name="gender" value="1">男
<input v-model="gender" type="radio" name="gender" value="2">女
<br><br>
<!--
前置理解:
1.option 需要设置 value 值,提交给后台
2.select 的 value 值,关联了选中的 option 的 value 值
结合 Vue 使用 → v-model
-->
所在城市:
<select v-model="cityId">
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">成都</option>
<option value="104">南京</option>
</select>
<br><br>
自我描述:
<textarea v-model="desc"></textarea>
<button>立即注册</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
username: '',
isSingle: true,
gender: "1",
cityId: '102',
desc: ""
}
})
</script>
</body>
</html>
计算属性
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性</title>
</head>
<body>
<!--
计算属性
概念:基于现有的数据,计算出来的新属性。依赖的数据变化,自动重新计算。
语法:
① 声明在 computed 配置项中,一个计算属性对应一个函数
② 使用起来和普通属性一样使用 { { 计算属性名 }}
计算属性 → 可以将一段 求值的代码 进行封装
data: {
list: [
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 2 },
{ id: 3, name: '铅笔', num: 5 },
]
},
computed: {
计算属性名() {
基于现有数据,编写求值逻辑
return 结果
}
},
-->
<div id="app">
<h3>小黑的礼物清单</h3>
<table>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
<tr v-for="(item, index) in list" :key="item.id">
<td>{ { item.name }}</td>
<td>{ { item.num }}个</td>
</tr>
</table>
<!-- 目标:统计求和,求得礼物总数 -->
<p>礼物总数:{ { totalCount }} 个</p>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// 现有的数据
list: [
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 2 },
{ id: 3, name: '铅笔', num: 5 }
]
},
computed: {
totalCount () {
// 基于现有的数据,编写求值逻辑
// 计算属性函数内部,可以直接通过 this 访问到 app 实例
// console.log(this.list)
// 需求:对 this.list 数组里面的 num 进行求和 → reduce
let total = this.list.reduce((sum, item) => sum + item.num, 0)
return total
}
}
})
</script>
</body>
</html>
computed计算属性vs方法methods
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性</title>
</head>
<body>
<!--
computed 计算属性 vs methods 方法
computed 计算属性:
作用:封装了一段对于数据的处理,求得一个结果。
语法:
① 写在 computed 配置项中
② 作为属性,直接使用 → this.计算属性 { { 计算属性 }}
优势:
缓存特性(提升性能):
计算属性会对计算出来的结果缓存,再次使用直接读取缓存,
依赖项变化了,会自动重新计算 → 并再次缓存
methods 方法:
作用:给实例提供一个方法,调用以处理业务逻辑。(点按钮执行操作等)
语法:
① 写在 methods 配置项中
② 作为方法,需要调用 → this.方法名() { { 方法名() }} @事件名="方法名"
-->
<div id="app">
<!-- methods方法 -->
<h3>小黑的礼物清单<span>{ { totalCountFn() }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCountFn() }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCountFn() }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCountFn() }}</span></h3>
<!-- computed方法 -->
<h3>小黑的礼物清单<span>{ { totalCount }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCount }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCount }}</span></h3>
<h3>小黑的礼物清单<span>{ { totalCount }}</span></h3>
<table>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
<tr v-for="(item, index) in list" :key="item.id">
<td>{ { item.name }}</td>
<td>{ { item.num }}个</td>
</tr>
</table>
<p>礼物总数:{ { totalCount }} 个</p>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 2 },
{ id: 3, name: '铅笔', num: 5 }
]
},
methods: {
totalCountFn () {
console.log('methods方法执行了') // 上面调用了四次,打印了四次次
let total = this.list.reduce((sum, item) => sum + item.num, 0)
return total
}
},
computed: {
// 计算属性:有缓存的,一旦计算出来结果,就会立刻缓存
// 下一次读取 → 直接读缓存 → 性能高
totalCount () {
console.log('计算属性执行了') // 上面调用了四次,只打印了一次
let total = this.list.reduce((sum, item) => sum + item.num, 0)
return total
}
}
})
</script>
</body>
</html>
计算属性的完整写法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性的完整写法</title>
</head>
<body>
<!--
计算属性完整写法
计算属性默认的简写,只能读取访问,不能"修改"。
如果要"修改" → 需要写计算属性的完整写法。
简写:
computed: {
计算属性名() {
一段代码逻辑(计算逻辑)
return 结果
}
}
完整:
computed: {
计算属性名: {
get() {
一段代码逻辑(计算逻辑)
return 结果
},
set(修改的值) {
一段代码逻辑(修改逻辑)
}
}
}
-->
<div id="app">
姓:<input type="text" v-model="firstName"> +
名:<input type="text" v-model="lastName"> =
<span>{ { fullName }}</span><br><br>
<button @click="changeName">改名卡</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: '刘',
lastName: '备'
},
methods: {
changeName () {
this.fullName = '吕小布'
}
},
computed: {
// 简写 → 获取,没有配置设置的逻辑
// fullName () {
// return this.firstName + this.lastName
// },
// 完整写法 → 获取 + 设置
fullName: {
// 当fullName计算属性,被获取求值时,执行get(有缓存,优先读缓存)
get () {
return this.firstName + this.lastName
},
// 当fullName计算属性,被修改赋值时,执行set
// 修改的值,传递给set方法的形参
set (value) {
this.firstName = value.slice(0,1)
this.lastName = value.slice(1)
}
}
}
})
</script>
</body>
</html>
watch_简写_语法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>watch_简写_语法</title>
</head>
<body>
<!--
watch 侦听器(监视器)
作用:监视数据变化,执行一些业务逻辑或异步操作。
语法:
① 简单写法 → 简单类型数据,直接监视
② 完整写法 → 添加额外配置项
data: {
words: '苹果',
obj: {
words: '苹果'
}
},
watch: {
// 该方法会在数据变化时,触发执行
数据属性名 (newValue, oldValue) {
一些业务逻辑 或 异步操作。
},
'对象.属性名' (newValue, oldValue) {
一些业务逻辑 或 异步操作。
}
}
-->
<div id="app">
翻译成的语言: <select>
<option>意大利</option>
</select>
<!-- 翻译框 -->
<div class="box">
<div class="input-wrap">
<textarea v-model="obj.words"></textarea>
<span><i></i>文档翻译</span>
</div>
<div class="output-wrap">
<div class="transbox">{ { result }}</div>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// 根属性
// words: '',
obj: {
// 子属性
words: ''
},
result: '', // id翻译结果
// timer: null // 延时器id
},
// 具体讲解: (1) watch语法 (2) 具体业务实现
watch: {
// 该方法会在数据变化时调用执行
// newValue新值, oldValue老值 (一般不用)
// words (newValue) {
// console.log('变化了', newValue)
// },
'obj.words' (newValue) {
// console.log('变化了', newValue)
// 防抖:延迟执行
clearInterval(this.timer)
this.timer = setTimeout(async () => {
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/api/translate',
params: {
words: newValue
}
})
this.result = res.data.data
console.log(res.data.data)
},300)
}
}
})
</script>
</body>
</html>
watch_完整写法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>watch_完整写法</title>
</head>
<body>
<!--
watch 侦听器(监视器)
② 完整写法 → 添加额外配置项
(1) deep: true 对复杂类型深度监视
(2) immediate: true 初始化立刻执行一次handler方法
data: {
obj: {
words: '苹果',
lang: 'italy'
}
},
// watch 完整写法
watch: {
数据属性名: {
deep: true, // 深度监视
handler (newValue) {
console.log(newValue)
}
}
}
-->
<div id="app">
<!-- 条件选择框 -->
<div class="query">
<span>翻译成的语言: </span>
<select v-model="obj.lang">
<option value="italy">意大利</option>
<option value="english">英语</option>
<option value="german">德语</option>
</select>
</div>
<!-- 翻译框 -->
<div class="box">
<div class="input-wrap">
<textarea v-model="obj.words"></textarea>
<span><i></i>文档翻译</span>
</div>
<div class="output-wrap">
<div class="transbox">{ { result }}</div>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 需求:输入内容,修改语言,都实时翻译
const app = new Vue({
el: '#app',
data: {
obj: {
words: '小黑',
lang: 'italy'
},
result: '', // id翻译结果
},
watch: {
obj: {
deep: true, // 深度监视
immediate: true, // 初始化立刻执行一次handler方法
handler (newValue) {
// console.log('对象被修改了', newValue)
clearInterval(this.timer)
this.timer = setTimeout(async () => {
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/api/translate',
params: newValue
})
this.result = res.data.data
console.log(res.data.data)
},300)
}
}
// 'obj.words' (newValue) {
// clearInterval(this.timer)
// this.timer = setTimeout(async () => {
// const res = await axios({
// url: 'https://applet-base-api-t.itheima.net/api/translate',
// params: {
// words: newValue
// }
// })
// this.result = res.data.data
// console.log(res.data.data)
// },300)
// }
}
})
</script>
</body>
</html>
生命周期和生命周期的四个阶段
生命周期两个例子_初始化渲染
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生命周期两个例子_初始化渲染</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list" :key="item.id" class="news">
<div class="left">
<div class="title">{ { item.title }}</div>
<div class="info">
<span>{ { item.source }}</span>
<span>{ { item.time }}</span>
</div>
</div>
<div class="right">
<img :src="item.img" alt="">
</div>
</li>
</ul>
</div>
<script src="./vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
//接口地址:http://hmajax.itheima.net/api/news
//请求方式:get
const app = new Vue({
el: '#app',
data: {
list: []
},
async created () {
// 1. 发送请求,获取数据
const res = await axios.get('http://hmajax.itheima.net/api/news')
// 2. 将数据更新给 data 中的 list
this.list = res.data.data
}
})
</script>
</body>
</html>
28_生命周期两个例子_获取焦点
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生命周期两个例子_获取焦点</title>
</head>
<body>
<div class="container" id="app">
<div class="search-container">
<img src="https://www.itheima.com/images/logo.png" alt="">
<div class="search - box">
<input type="text" v-model="words" id="inp">
<button>搜索一下</button>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
words: ''
},
//核心思路:
//1.等输入框渲染出来
//2.让输入框获取焦点
mounted () {
document.querySelector('#inp').focus()
}
})
</script>
</body>
</html>
项目目录介绍和运行流程
main.js
// 文件核心作用:导入App.vue,基于App.vue创建结构渲染index.html
// 1. 导入 Vue 核心包
import Vue from 'vue'
// 2. 导入 App.vue 根组件
import App from './App.vue'
import router from './router'
import store from './store'
// 提示:当前处于什么环境(生产环境 / 开发环境)
Vue.config.productionTip = false
// 3. Vue实例化,提供render方法 -> 基于App.vue创建结构渲染index.html
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<!-- 兼容:给不支持js的浏览器一个提示 -->
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!-- Vue所管理的容器:将来创建结构动态渲染这个容器 -->
<div id="app">
<!-- 工程化开发模式中:这里不再直接编写模板语法,而是通过App.vue提供结构渲染 -->
</div>
<!-- built files will be auto injected -->
</body>
</html>
组件化开发和根组件
APP.vue
<!-- template结构(有且只能有一个根元素) -->
<template>
<div class="App">
<div class="box" @click="fn"></div>
</div>
</template>
<!-- script -->
<script>
// 导出当前组件的配置项
// 里面可以提供data methods computed 生命周期八大钩子
export default {
methods: {
creat () {
console.log('我是created')
},
fn () {
alert('你好')
}
}
}
</script>
<!-- style样式 -->
<style lang="less">
.App {
width: 400px;
height: 400px;
background-color: pink;
.box {
width: 100px;
height: 100px;
background-color: skyblue;
}
}
</style>