1、插值表达式,{{ }}
可以插数据,计算式,方法函数fn(return),布尔值
<body>
<!-- 插值表达式
1、支持表达式,不支持语句 if for
2、不能直接在属性值中插值使用
3、响应式,数据变化,视图自动更新
-->
<div id="app">
{{msg}}
<p>{{count}}</p>
<p>{{nickname}}</p>
<div>{{nickname.toUpperCase()}}</div>
<div>{{nickname + '你好'}}</div>
<p>{{age >= 18 ? '成年' : '未成年'}}</p>
<div>{{friend.name + friend.desc}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',//指定vue管理的选择器
data: {
msg: 'hello 传智播客',
count: 666,
nickname: 'tony',
age: 19,
friend: {
name: 'pink',
desc: '热爱学习vue'
}
}
})
</script>
</body>
2、vue指令v-前缀,官网文档v-指令。v-XX="内联语句,计算,比较,函数名等"
<body>
<!-- v-html功能相当于innerhtml,用来解析H5标签 -->
<!-- v-show是通过控制css的display: none;来控制元素的显示和隐藏,用于频繁切换的场景 -->
<!-- v-if是通过渲染来控制,用于不平凡的切换 -->
<!-- v-on:事件绑定,v-on:可以替换为@。如@click -->
<!-- v-bind: = :用于标签属性的动态传参,可以简写为:加属性名,如url等 -->
<!-- v-for="(item,index)in 数组名" 遍历数组。 :key是用来给列表一个唯一标识正确排序,防止错误编码 -->
<!-- v-model双向数据绑定,视图和数据双向绑定 -->
<div id="app">
<div v-html="msg"></div>
<div v-show="flag" class="box">我是v-show控制的盒子</div>
<div v-if="score >= 90" class="box">大于等于90</div>
<div v-else-if="score >= 70" class="box">大于70</div>
<div v-else class="box">小于70</div>
<div class="box" v-show="flag">值为{{score}}</div>
<button class="box" v-on:click="score++">+</button>
<button class="box" @click="score--">-</button>
<button class="box" @click="fn">值隐藏</button><br>
<button @click="buy(5)">可乐5元</button>
<button @click="buy(10)">咖啡10元</button>
<img :src="imgUrl" v-bind:title="mmg" alt="">
<ul>
<li v-for="(item,index) in list">{{item}}--{{index}}</li>
</ul>
输入框<input type="text" v-model="username">
<button @click="reset">清空</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
mmg: '哈哈哈哈',
msg: `<a href="#">学前端~来黑马!</a>`,
flag: true,
score: 92,
imgUrl: './imgs/10-01.png',
list: ['西瓜', '苹果', '香蕉'],
username: '哈哈哈'
},
methods: {
fn() {//this指向app,this.flag = app.flag
this.flag = !this.flag
},
buy(a) {
this.score -= a
},
reset() {
this.username = ''
}
}
})
</script>
3、指令修饰符
1、事件绑定 @keyup.enter="add",监听键盘回车事件,@keyup.键盘="函数名" 2、v-model修饰符,v-model.number将填写内容字符串转化为数字,v-model.trim清除首尾空格
<input type="text" v-model.number="price" />
//这个判断条件的使用必须基于,v-model.number来判断,否则写入的是数字也无法通过
if (typeof this.price !== 'number') {
alert('请输入正确的消费价格')
return
}
3、@事件名.stop阻止冒泡和@事件名.prevent。如:@click.stop="add"
4、v-bind操作class和style,后面是单引号
<div class="box" :class="{ pink: true, big: x >= y }">黑马程序员</div>
<div class="box" :class="['pink', 'big']">黑马程序员</div>
注意这里style多个属性是用,连接的
<div class="inner"
:style="{ width: percent + '%',height: percent + '%' }">
<span>{{ percent }}%</span>
</div>
5、计算属性 computed ,一定要return返回值
计算属性——>对内部的data值进行求和或计算,在return返回给vue
<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: {
//与data统计
totalCount() {
//0是起始值,sum是累加的和
let total = this.list.reduce((sum, item) => sum + item.num, 0)
return total
}
}
})
</script>
6、计算机属性computed与方法methods的区别
computed不用调用可直接计算缓存下来,侧重数据的处理计算,只执行一次
7、计算属性的完整写法computed,get(),set()
<div id="app">
姓:<input type="text" v-model="first"><br>
名:<input type="text" v-model="last"><br>
<p>姓名:{{full}}</p>
<button @click="chang">修改姓名</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
first: '刘',
last: '备'
},
computed: {
// full() {
// return this.first + this.last
// }
full: {
get() {
return this.first + this.last
},
set(v) {
this.first = v.slice(0, 1)
this.last = v.slice(1)
}
}
},
methods: {
chang() {
this.full = '吕小布'
}
}
})
</script>
8、watch监听器,执行异步操作或业务逻辑
const app = new Vue({
el: '#app',
data: {
// words: ''
obj: {
words: ''
}
},
// 具体讲解:(1) watch语法 (2) 具体业务实现
watch: {
// 该方法会在数据变化时调用执行
// newValue新值, oldValue老值(一般不用)
// words (newValue) {
// console.log('变化了', newValue)
// }
'obj.words'(newValue) {
// console.log('变化了', newValue)
//防止一段时间内多次请求
// 防抖: 延迟执行 → 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
clearTimeout(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)
}
}
}
})
9、watch监听器的完整写法
const app = new Vue({
el: '#app',
data: {
obj: {
words: '小黑',
lang: 'italy'
},
result: '', // 翻译结果
},
watch: {
obj: {
deep: true, // 深度监视,可以监听对象中的所有属性
immediate: true, // 立刻执行,一进入页面handler就立刻执行一次
handler(newValue) {
clearTimeout(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)
}
}
}
})
10、生命周期:创建,挂载,更新,销毁(8个钩子函数,一个阶段两个)
关键的两个created(初始化操作),mounted(操作dom)
//1、创建阶段
beforeCreate() {
},
created() {
//最重要请求渲染
},
//2、挂载阶段
beforeMount() {
},
mounted() {
//
},
//更新阶段
beforeUpdate() {
},
update() {
},
//卸载阶段
beforeDestroy() {
},
destroyed() {
}
created使用发送请求
<script>
// 接口地址:http://hmajax.itheima.net/api/news
// 请求方式:get
const app = new Vue({
el: '#app',
data: {
list: []
},
async created() {
const res = await axios.get('http://hmajax.itheima.net/api/news')
this.list = res.data.data
}
})
</script>
mounted使用操作dom
<script>
const app = new Vue({
el: '#app',
data: {
words: ''
},
mounted() {
//dom渲染完成输入框获取焦点
document.querySelector('#inp').focus()
}
})
</script>
11、mounted操作Echarts页面图标的实时更新
methods:{
async getlist() {
//重新渲染请求函数
const res = await axios.get('https://applet-base-api-t.itheima.net/bill', { params: { creator: '换行' } })
this.list = res.data.data
//那部分变了就更新哪部分
this.myC.setOption({
series: [
{
data: this.list.map(item => ({
value: item.price, name: item.name
})
)
}
]
})
}
},
mounted() {
//操作dom在页面上绘制出图标
this.myC = echarts.init(document.querySelector('#main'))
this.myC.setOption({
title: { //大标题
text: '消费列表',
left: 'center'
},
tooltip: { //提示框
trigger: 'item'
},
legend: { //图例的对其等
orient: 'vertical',
left: 'left'
},
series: [
{
name: '消费账单',
type: 'pie',
radius: '50%', //半径
data: [
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
})
}
})
12、工程化开发模式&手脚架Vue CLI
1、vue create p-name
2、yarn serve 或 npm run serve (找package.json)
13、组件化开发&根组件
1、局部注册 组件的注册和使用
<template>
<div class="App">
<hmHeader />
<hmMain></hmMain>
<hmFooter></hmFooter>
</div>
</template>
<script>
import hmHeader from './components/hmHeader.vue';
import hmMain from './components/hmMain.vue';
import hmFooter from './components/hmFooter.vue';
export default {
components: {
hmHeader: hmHeader,
hmMain,
hmFooter
}
}
</script>
2、全局注册,后全局可直接使用
//main.js文件全局注册
import Vue from 'vue'
import App from './App.vue'
import HmButton from './components/HmButton.vue'
Vue.component('HmButton', HmButton);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
14、多个组件的样式冲突问题,加scoped来解决
<style scoped>
</style>
15、data(){ return {} }写成一个函数,防止多次调用同一组件的数据干扰
export default{
data(){
return {
count: 188,
}
}
}
16、父子关系的组件通信,数据传递
1、父传子,props: [' ']
2、子传父,
this.$emit('change','传的内容')
17、props的校验 props:{ 属性名: 类型 }
props: {
w: {
type: Number,
required: true,//非空校验
default: 30,//默认值,空值填为默认值
validator(value) { //自定义校验
if (value >= 0 && value <= 100) {
return true
} else {
console.error('传入的值必须是0~100的数字')
return false
}
}
}
}
18、非父子关系的组件通讯,event bus事件总线,一对多
19、v-model="value"的原理 :value=""和@input事件的合写
在组件通讯时,用:value接收传来的值
<input type="text" v-model="msg1" /> //相同功能
<input type="text" :value="msg2" @input="msg2 = $event.target.value" />
20、.sync修饰符对比v-model的通讯写法
两种简写都是对子组件有命名约束
21、ref和$refs获取dom对象,echarts实例
父组件调用子组件的方法
this.$refs.子组件名.子组件的方法()
<template>
<div class="app">
<h4>父组件 -- <button>获取组件实例</button></h4>
<BaseForm ref="baseFrom"></BaseForm>
<div>
<button @click="getFormData">获取数据</button>
<button @click="resetFormData">重置数据</button>
</div>
</div>
</template>
<script>
import BaseForm from './components/BaseForm.vue'
export default {
components: {
BaseForm,
},
methods: {
getFormData() {
console.log(this.$refs.baseFrom.getFormData())
},
resetFormData() {
this.$refs.baseFrom.resetValues()
}
}
}
</script>
基于准备好的dom,初始化echarts实例
<template>
<div ref="mychart" class="base-chart-box">子组件</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
mounted() {
// 基于准备好的dom,初始化echarts实例
// const myChart = echarts.init(document.querySelector('.base-chart-box'))
const myChart = echarts.init(this.$refs.mychart)
// 绘制图表
myChart.setOption({
title: {
text: 'ECharts 入门示例',
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
},
],
})
},
}
</script>
<style scoped>
.base-chart-box {
width: 400px;
height: 300px;
border: 3px solid #000;
border-radius: 6px;
}
</style>
22、vue异步更新,用 this.$nextTick( () => { })
this.$nextTick( () => { })。等dom更新完成后,再立刻执行this.$nextTick( () => { })中的语句
1、自定义指令,v- 指令
全局注册指令,在main.js中注册
Vue.directive('focus', {
inserted(el) { //组件插入页面时触发这个钩子
el.focus()
}
})
局部注册,组件内部自己使用
<template>
<div>
<h1>自定义指令</h1>
<input v-focus type="text">
</div>
</template>
<script>
export default {
directives: {
focus: {
inserted(el) {
el.focus()
}
}
}
}
</script>
自定义指令的传参,数据的绑定,更新
<template>
<div>
<h1 v-color="color1">自定义指令1111</h1>
<h1 v-color="color2">自定义指令2222</h1>
</div>
</template>
<script>
export default {
data() {
return {
color1: 'red',
color2: 'green'
}
},
directives: {
color: {
inserted(el, binding) { //渲染时的钩子
el.style.color = binding.value
},
update(el, binding) { //更新时的钩子
el.style.color = binding.value
}
}
}
}
</script>
常用自定义的指令,v-loading加载展示的指令
加载动画的实现效果
<template>
<div class="main">
<div class="box" v-loading="isLodaing"></div>
<div class="box2" v-loading="is2"></div>
</div>
</template>
<script>
// 安装axios => yarn add axios
import axios from 'axios'
export default {
data() {
return {
list: [],
isLodaing: true,
is2: true
}
},
async created() {
const res = await axios.get('http://hmajax.itheima.net/api/news')
setTimeout(() => {
// 2. 更新到 list 中
this.list = res.data.data
this.isLodaing = false
}, 2000)
},
directives: {
loading: {
inserted(el, binding) {
binding.value ? el.classList.add('loading') : el.classList.remove('loading')
},
update(el, binding) {
binding.value ? el.classList.add('loading') : el.classList.remove('loading')
}
}
}
}
</script>
<style>
/* 伪类 - 蒙层效果 */
.loading:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #fff url('./loading.gif') no-repeat center;
}
2、插槽,让组件的内部的一些结构支持自定义,(如文字,样式等)
1、定义,使用方法
2、默认值,<solt>默认值</solt>后备内容
3、具名插槽,一个组件需要多个地方要定制,就要给<slot name="">定义名字
4、作用域插槽,定义slot的同时,是可以传递数据的
3、路由VueRouter的使用
在main.js中注册
1、自定义匹配的类名,高亮选择的类名
2、声明式导航跳转传参
记得加?号
{ path: '/search/:words?', component: Search },
3、路由重定向,起始页面的配置,{path: '/',redirect: '/home'}
4、vue路由404,{path: '*',component: NotFind}
要建立NotFind.vue文件,展示此文件的页面
5、去出导航的#,转换为历史路由
6、编程式导航-基本跳转-传参
7、二级路由,子路由,children: [{path: ,component: }]
8、返回上一页
9、动态传参
静态用query