01 Vue基本
javascript
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ msg }}</h2>
</div>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> -->
<script src="./vue.js"></script>
<script>
// 实例vm
// MVVM :
// 1. M Model data中的数据
// 2. V View 视图,展示在页面上html结构
// 3. VM ViewModel 把它当做Vue实例
const vm = new Vue({
// 不建议data写成对象
// data:{
// msg:'你好呀,下午好'
// },
// data:function(){
// return {
// msg:'yo'
// }
// },
// data存放数据变量的,要写成一个函数
data(){
return {
msg:'yohuohuo'
}
}
// el:'#app',
// 1. 如果有template,会以template模板的内容挂载到HTML上
// 2. 如果没有template,会直接以#app这个节点作为模板展示内容
// template:'<div>{{ msg }}</div>'
})
// 3秒之后显示这个模板
setTimeout(function(){
// mount 就是挂载的意思,把模板挂载到#app节点上
vm.$mount('#app')
}, 1000)
</script>
</body>
</html>
02 插值语法
javascript
<div id="app">
<h2>{{ msg }}</h2>
{{ msg2 }}
<!-- {{ demo }} -->
<!-- 3. 属性值不能写插值语法 -->
<!-- <div class="{{ color }}"></div> -->
<div v-bind:class="color"></div>
<div :class="color"></div>
</div>
<script src="./vue.js"></script>
<script>
const vm = new Vue({
el:'#app',
data(){
return {
msg:'我是msg',
// 1. 插值语法,需要注意,标签会当做普通文本解析
// 2. {{}} 中的变量,一定要在data中存在,不存在,会报错
// 3. 标签的属性上,不能使用{{}} ,也会报错
msg2:'<p>123</p>',
color:'red'
}
}
})
</script>
03 v-bind注意事项
javascript
<div id="app">
<div v-bind:class="msg"></div>
<!-- 1. : v-bind msg ==> 变量,需要再data中去寻找这个变量 -->
<div :class="msg"></div>
<!-- 2. 不加冒号 msg 是一个普通的字符串,写死的 -->
<div class="msg"></div>
</div>
<script>
// v-bind 让标签的某些属性和我们data中的数据做一个绑定
// 绑定:有了相互的关系,数据变化了,属性值也会改变
</script>
<script src="./vue.js"></script>
<script>
const vm = new Vue({
el:'#app',
data(){
return {
msg:'我是msg',
}
}
})
</script>
04 v-on 注册事件
javascript
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="count++">{{ count }}</button>
<button @click="addCount">{{ num }}</button>
<h2>{{ money }}</h2>
<button @click="eat('建国')">请建国吃饭</button>
<button @click="eat('海龙')">请海龙吃饭</button>
</div>
<script src="./vue.js"></script>
<script>
// 1. v-on 注册事件
// 2. 语法:
// 1. v-on:事件名 = 要执行的少量代码
// 2. v-on:事件名 = methods中的函数
// 3. v-on:事件名 = methods中函数名(传参1,传参2...)
// 3. v-on 简写 @
new Vue({
el:'#app',
data(){
return {
count:100,
num:1000,
money:500
}
},
methods:{
addCount(){
this.num++
},
eat(person){
if(person === '建国'){
this.money -= 10
}
if(person === '海龙'){
this.money -= 100
}
}
}
})
</script>
</body>
</html>
04 组件的注册
javascript
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
</head>
<body>
<div id="app">
<button-counter></button-counter>
<h2>我是局部组件</h2>
<component-a></component-a>
</div>
<script src="./vue.js"></script>
<script>
// 定义一个名为 button-counter 的新组件
// 1. 先注册组件
// Vue.component 是一个全局组件
Vue.component('button-counter', {
data () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
// 2。 局部注册组件
// 通过一个普通的对象来注册组件。。 ===> .vue单文件组件
const componentA = {
data(){
return {
num:100
}
},
// 当前这个组件的结构 tempalte中只有一个根标签
template: `
<div>
<button-counter></button-counter>
<button @click=num++>{{ num }}</button>
</div>
`
}
// 组件:组件就是页面上的一个部分,一个模块
// 可以包含 html / js / css
const vm = new Vue({
el:'#app',
data(){
return {
count:100,
msg:'我是msg',
}
},
components:{
// components 左边的key就是我们要使用的组件名
'component-a': componentA
}
})
</script>
</body>
</html>
05 创建Vue项目
javascript
Vue create vue-demo
- package.json
javascript
"start": "vue-cli-service serve",
// npm run start ==> 如果是start ,可以简写为 npm start
// yarn start
全局注册组件
javascript
创建一个 GlobalDemo
vue
<template>
<!-- 只能有一个根标签 -->
<div>
<h2>{{ msg }}</h2>
</div>
</template>
<script>
export default {
data(){
return {
msg:'我是全局注册的组件'
}
}
}
</script>
<style>
</style>
javascript
import Vue from 'vue'
import App from './App.vue'
// 1. 导入 import
import GobalDemo from './components/GlobalDemo.vue'
Vue.config.productionTip = false
// 2. 全局注册 左边是组件名,右边是组件对象
// ---> 使用的时候,可以短横线 global-demo
Vue.component('GlobalDemo', GobalDemo)
new Vue({
render: h => h(App),
}).$mount('#app')
06 终端报错
右键以管理员身份运行
javascript
set-ExecutionPolicy RemoteSigned
07 nrm
javascript
npm i nrm -g 全局安装
// 1. nrm ls 查看资源地址
// 2. nrm test 测试下载速度
// 3. nrm use taobao 使用淘宝镜像安装
08 组件注册建议驼峰命名
- 组件名,多单词
- 组件名建议大驼峰
javascript
// 1. 导入 import
import GobalDemo from './components/GobalDemo.vue'
Vue.config.productionTip = false
// 2. 全局注册
// 1. 这里注册的名字,如果都是驼峰大写,在组件内使用的时候,
// 可以大写,也可以中横线
// 2. 如果这里写短横线的形式,组件内使用,只能是短横线
// ===> 推荐 :命名 驼峰大写
Vue.component('GlobalDemo', GobalDemo)
09 局部注册组件
javascript
<template>
<div>
<button>{{ msg }}</button>
</div>
</template>
<script>
export default {
data(){
return {
msg:'我是局部组件'
}
}
}
</script>
<style>
</style>
javascript
<template>
<div id="app">
<global-demo></global-demo>
<!-- <GlobalDemo></GlobalDemo> -->
<!-- 组件在.vue中使用的时候,三种都可以 -->
<ButtonDemo></ButtonDemo>
<button-demo></button-demo>
<button-demo/>
</div>
</template>
<script>
import ButtonDemo from './components/ButtonDemo.vue'
export default {
name: 'App',
components:{
ButtonDemo
}
}
</script>
10 计算属性
javascript
<template>
<div>
<h2>计算属性</h2>
<div>{{ sum }}</div>
</div>
</template>
<script>
export default {
data(){
return {
num1 : 10,
num2 : 12
}
},
// computed这里是对象
computed:{
// sum是一个方法,但是当做属性来使用
sum(){
// this指向的是vue的实例
return this.num1 + this.num2
// 1. 计算属性是一个函数,这个函数要写return!!
// 2. 当依赖的数据(num1,num2)改变的时候,sum的值也一起发生改变
// 3. this指向的是vue的实例
// 4. 使用的时候,不加括号,当做属性使用(和data中定义的数据一样,当做变量使用)
}
}
}
</script>
<style>
</style>
11 计算属性有缓存
javascript
<template>
<div>
<h2>计算属性</h2>
<div>{{ sum }}</div>
<div>{{ sum }}</div>
<div>{{ sum }}</div>
<div>{{ sum }}</div>
<h3>这是方法调用</h3>
<div>{{ sumFn() }}</div>
<div>{{ sumFn() }}</div>
<div>{{ sumFn() }}</div>
<div>{{ sumFn() }}</div>
</div>
</template>
<script>
export default {
data(){
return {
num1 : 10,
num2 : 12
}
},
methods:{
sumFn(){
console.log('这是方法调用')
return this.num1 + this.num2
}
},
// computed这里是对象
computed:{
// sum是一个方法,但是当做属性来使用
sum(){
console.log('这是计算属性')
// this指向的是vue的实例
return this.num1 + this.num2
// 1. 计算属性是一个函数,这个函数要写return!!
// 2. 当依赖的数据(num1,num2)改变的时候,sum的值也一起发生改变
// 3. this指向的是vue的实例
// 4. 使用的时候,不加括号,当做属性使用(和data中定义的数据一样,当做变量使用)
}
}
}
// ===>
// 1. 计算属性会缓存结果,只要依赖项不变,直接读取缓存
// 2. 如果依赖项改变,重新计算并缓存最新的结果
// 使用场景:
// 1. 求和,求平均值等
// 2. 全选反选
</script>
<style>
</style>
12 计算属性高级写法
当我们需要修改计算属性的时候,使用 set
javascript
<template>
<div>
姓<input type="text" v-model="firstName">
名<input type="text" v-model="lastName">
<h2>{{ fullName }}</h2>
<button @click="changeName">改变名字</button>
</div>
</template>
<script>
export default {
data(){
return {
firstName:'小野',
lastName:'太郎'
}
},
methods:{
changeName(){
console.log(111)
this.fullName = '罗广-太君'
}
},
computed: {
// 如果要修改计算属性
// fullName () {
// return this.firstName + '-' + this.lastName
// },
fullName:{
// getter函数 --> 当我们读取fullName的时候
get(){
return this.firstName + '-' + this.lastName
},
set(newVal){
// 我们需要基于修改的值,更新依赖项,依赖项更新,计算属性自然而然就会更新
console.log(newVal)
// 字符串转数组
const arr = newVal.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
}
</script>
<style>
</style>
12 watch侦听器
javascript
<template>
<div>
<h3>银行卡余额{{ money }}</h3>
<button @click='money = money + 10000'>发工资</button>
<button @click='money = money - 20'>干饭</button>
<button @click='changeAge'>花花长了一岁</button>
<button @click='changePerson'>他变了</button>
</div>
</template>
<script>
export default {
data(){
return {
money: 100,
obj:{
name:'花花', // 顶流女明星 大熊猫 panda
age:3
},
// 监听这个人各个变化
person:{
name:'嫌疑犯',
age:18,
desc:'喜欢踩点,蹦迪,唱跳rap'
}
}
},
methods:{
changeAge(){
this.obj.age++
},
changePerson(){
this.person.age++
}
},
watch:{
// 监听data中money改变
// 1.1. 第一种写法
money(newVal, oldVal){
console.log('尊敬的Vip用户,你的余额变更为'+newVal, '原来是' + oldVal)
},
// 1.2. 第二种写法
'money'(newVal, oldVal){
console.log('尊敬的Vip用户,你的余额变更为'+newVal, '原来是' + oldVal)
},
// 2.监听对象中的某个值
'obj.age'(newVal, oldVal){
console.log(`花花的年龄现在是${newVal}, 原来是${oldVal}`)
},
// 3. 监听一个对象的所有属性,只要有一个变化了,就会触发
person:{
deep:true,
immediate:true, // 一进入页面,首先执行一次
// 对于复杂类型的监听,newVal和oldVal 会指向同一个对象,所以oldVal意义不大
// handler(val, oldVal){
// console.log(val, oldVal)
// console.log(val === oldVal)
// }
handler(val){
console.log(val)
}
}
}
}
</script>
<style>
</style>
13 父组件给子组件传值
javascript
<template>
<div id="app">
<!--
父组件,
1. 父组件通过给子组件,添加标签属性传值
2. 子组件props接收
-->
<h2>建国的黑店</h2>
<!-- <my-product title='无敌猪肘子' price="199" desc="好吃极了" />
<my-product title='爽口大西瓜' price="99" desc="忒甜了" />
<my-product title='红烧大排骨' price="299" desc="贵死了" /> -->
<!-- 加冒号和不加冒号的区别: 是否是动态绑定,动态绑定的意思就是使用的是data中的数据 -->
<my-product v-for="item in list" :key="item.id"
:title="item.title"
:price="item.price"
/>
</div>
</template>
<script>
import MyProduct from './components/MyProduct.vue'
// import ComputedAdvance from './components/ComputedAdvance.vue'
// import WatchDemo from './components/WatchDemo.vue'
export default {
name: 'App',
data(){
return {
list: [
{ id: 1, title: '无敌猪肘子', price: 188 },
{ id: 2, title: '爽口大西瓜', price: 360},
{ id: 3, title: '美味大闸蟹', price: 42}
]
}
},
components:{
// ComputedAdvanc,
// WatchDemo,
MyProduct
}
}
</script>
子组件props接收
javascript
<template>
<!-- 子组件 -->
<div class="goods">
<h3>{{title}}</h3>
<p>{{price}}</p>
<!-- <p>{{desc}}</p> -->
</div>
</template>
<script>
export default {
name:'MyProduct',
props:['title', 'price', 'desc']
}
</script>
14 子组件给父组件传参
父组件 App.vue
javascript
<template>
<div id="app">
<!--
父组件,
1. 想要往子组件传参,添加标签属性传值
2. 子组件props接收
-->
<h2>建国的黑店</h2>
<!-- <my-product title='无敌猪肘子' price="199" desc="好吃极了" />
<my-product title='爽口大西瓜' price="99" desc="忒甜了" />
<my-product title='红烧大排骨' price="299" desc="贵死了" /> -->
<!-- 加冒号和不加冒号的区别: 是否是动态绑定,动态绑定的意思就是使用的是data中的数据 -->
<my-product v-for="item in list" :key="item.id"
:title="item.title"
:price="item.price"
:desc="item.desc"
@changePrice="handlePrice"
/>
</div>
</template>
<script>
import MyProduct from './components/MyProduct.vue'
// import ComputedAdvance from './components/ComputedAdvance.vue'
// import WatchDemo from './components/WatchDemo.vue'
export default {
name: 'App',
data(){
return {
list: [
{ id: 1, title: '无敌猪肘子', price: 188 ,desc:'美味极了'},
{ id: 2, title: '爽口大西瓜', price: 360, desc:'爽歪歪'},
{ id: 3, title: '美味大闸蟹', price: 42, desc:'泰裤辣'}
]
}
},
methods:{
// changePrice(val){
// console.log(val)
// this.list[0].price -= val
// }
handlePrice(price, id){
const good = this.list.find(el => el.id === id) // 找到要修改的那个对象
good.price -= price
}
},
components:{
// ComputedAdvanc,
// WatchDemo,
MyProduct
}
}
</script>
子组件 MyProduct
javascript
<template>
<!-- 子组件 -->
<div class="goods">
<h3>{{title}}</h3>
<p>{{price}}</p>
<p>{{desc}}</p>
<button @click='cutPrice'>砍一刀</button>
</div>
</template>
<script>
export default {
name:'MyProduct',
props:['title', 'price', 'desc'],
methods:{
cutPrice(){
// 不能再子组件中去修改父组件穿过来的props值
// 数据流向 ==> 从父组件,到子组件
// this.price = this.price - 10
// 如果自组件想要修改父组件传的数据
// 怎么办呢,通知父组件,让父组件自己去修改这个数据
// 1. 第一个参数,子组件自定义的事件名,这个事件会在组件注册监听
// 2. 第二个参数,要传递给父组件的参数(信息)
// 如果要给对应的那个对象砍一刀,可以给一个id标识
this.$emit('cutPrice', 10, id)
// this.$emit('changePrice', 10)
}
}
}
</script>