参照视频coderwhy老师的Vue
目前笔记积累到P62
原本没打算整理笔记,结果p63看懵了,然后开始整理起来笔记
部分笔记参考Vue笔记整理
某些时候我们并不想将变量放在标签内容中,像这样
是将变量h2标签括起来,类似js的innerHTML。但是我们期望将变量{{message}}
imgURL
写在如下位置,想这样导入图片是希望动态获取图片的链接,此时的imgURL并非变量而是字符串imgURL。
如果要将其生效为变量,需要使用到一个标签v-bind:
,像这样,而且这里也不能使用Mustache语法,类似
,这也是错误的。
v-bind:由于用的很多,vue对他有一个语法糖的优化写法也就是
:,如
有时候我们期望对Dom元素的节点的class进行动态绑定,选择此Dom是否有指定class属性。例如,给h2标签加上class="active"
,当Dom元素有此class时候,变红,在写一个按钮绑定事件,点击变黑色,再次点击变红色。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>v-bind动态绑定class(对象语法)</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="app">
<!-- 动态绑定class对象用法 -->
<!--
<h2 :class="{key1:value1,key2:value2}">{{message}}</h2>
<h2 :class="{类名1:true,类名2:boolean}">{{message}}</h2>
-->
<h2 class="title" :class="{active:isActive}">{{message}}</h2>
<h2 class="title" :class="getClasses()">{{message}}</h2>
<button @click="change">点击变色</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"你好啊",
active:"active",
isActive:true
},
methods: {
change(){
this.isActive = !this.isActive
},
getClasses(){
return {active:this.isActive}
}
},
})
</script>
</body>
</html>
定义两个变量active
和isActive
,在Dom元素中使用:class={active:isActive}
,此时绑定的class='active'
,isActive为true,active显示,定义方法change()绑定在按钮上,点击按钮this.isActive = !this.isActive
,控制Dom元素是否有class='active'
的属性。
class属性中可以放数组,会依次解析成对应的class。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>v-bind动态绑定class(数组用法)</title>
<style>
</style>
</head>
<body>
<div id="app">
<!-- 加上单引号当成字符串 -->
<h2 class="title" :class="['active','line']">{{message}}</h2>
<!-- 不加会被当成变量 -->
<h2 class="title" :class="[active,line]">{{message}}</h2>
<h2 class="title" :class="getClasses()">{{message}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"你好啊",
active:"aaaa",
line:'bbbb'
},
methods: {
getClasses(){
return [this.active,this.line]
}
},
})
</script>
</body>
</html>
<!-- <h2 :style="{key(属性名):value(属性值)}">{{message}}</h2> -->
<!-- 加单引号,当成字符串解析 -->
<h2 :style="{fontSize:'50px'}">{{message}}</h2>
<!-- 不加单引号,变量解析 -->
<h2 :style="{fontSize:fontSize}">{{message}}</h2>
<h2 :style="getStyle()">{{message}}</h2>
<div id="app">
<h2 :style="[baseStyle]">{{message}}</h2>
<h2 :style="getStyle()">{{message}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"你好啊",
baseStyle:{backgroundColor:'red'}
},
methods: {
getStyle(){
return [this.baseStyle]
}
},
})
</script>
类似绑定class,绑定style也是一样的。
在计算属性中其实是由这样两个方法setter和getter。
computed: {
fullName:{
//计算属性一般没有set方法,只读属性
set:function(newValue){
console.log("-----")
const names = newValue.split(" ")
this.firstName = names[0]
this.lastName = names[1]
},
get:function(){
return this.firstName + " " + this.lastName
}
}
}
但是计算属性一般没有set方法,只读属性,只有get方法,但是上述中newValue就是新的值,也可以使用set方法设置值,但是一般不用。
computed的getter/setter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue计算属性的getter和setter</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>计算属性:computed的getter/setter</h1>
<h2>fullName</h2>
{{fullName}}
<h2>firstName</h2>
{{firstName}}
<h2>lastName</h2>
{{lastName}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
firstName:"zhang",
lastName:"san",
},
computed: {
fullName:{
get:function(){
return this.firstName+" "+this.lastName
},
set:function(value){
var list = value.split(' ');
this.firstName=list[0]
this.lastName=list[1]
}
}
},
});
</script>
</body>
</html>
使用v-on:click
给button绑定监听事件以及回调函数,@是v-on:
的语法糖,也就是简写也可以使用@click
。方法一般是需要写方法名加上(),在@click
中可以省掉,如上述的。
如果我们需要event对象还需要传入其他参数,可以使用$event
对象。
event.stopPropagation()
。event.preeventDefault
阻止默认行为。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message">{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "hello"
}
})
</script>
</body>
</html>
v-model双向绑定,既输入框的value改变,对应的message对象值也会改变,修改message的值,input的value也会随之改变。无论改变那个值,另外一个值都会变化。
v-model的原理
v-model
-> v-bind:value
v-on:input
<div id="app">
<input type="text" v-model="message">
<input type="text" :value="message" v-on:input="valueChange">
<input type="text" :value="message" @input="message = $event.target.value">
{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data :{
message : 'hello'
},
methods :{
valueChange(event){
this.message = event.target.value;
}
}
})
</script>
实现双向绑定需要是用v-bind和v-on,使用v-bind给input的value绑定message对象,此时message对象改变,input的值也会改变。但是改变input的value并不会改变message的值,此时需要一个v-on绑定一个方法,监听事件,当input的值改变的时候,将最新的值赋值给message对象。$event
获取事件对象,target获取监听的对象dom,value获取最新的值。
v-model结合radio
radio单选框的name
属性是互斥的,如果使用v-model,可以不使用name
就可以互斥。
<div id="app">
<label for="male">
<input type="radio" id="male" name='sex' value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" name='sex' value="女" v-model="sex">女
</label>
<h2>{{sex}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data :{
message : 'hello',
sex : ''
}
})
</script>
v-model绑定sex
属性,初始值为“男”,选择女后sex
属性变成“女”,因为此时是双向绑定。
v-model结合chechbox
<div id="app">
<label for="license">
<input type="checkbox" id="license" v-model="isAgree" />同意协议
</label>
<br />
{{isAgree}}
<button :disabled="!isAgree">下一步</button>
<br />
<label for="1">
<input type="checkbox" value="篮球" id="1" v-model="hobbies" />篮球
</label>
<label for="2">
<input type="checkbox" value="足球" id="2" v-model="hobbies" />足球
</label>
<label for="3">
<input type="checkbox" value="乒乓球" id="3" v-model="hobbies" />乒乓球
</label>
<label for="4">
<input type="checkbox" value="吃饭" id="4" v-model="hobbies" />吃饭
</label>
<br />
{{hobbies}}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "hello",
isAgree: false,
hobbies: [],
},
});
</script>
isAgree
初始化为false
,点击checkbox的值为true
,isAgree
也是true
。hobbies
,用于存放爱好,将hobbies
与checkbox对象双向绑定,此时选中,一个多选框,就多一个true,hobbies
就添加一个对象。v-model结合select可以单选也可以多选
v-model结合select可以单选也可以多选
<div id="app">
<!-- 选择一个 -->
<select name="abc" v-model="fruit">
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="grape">grape</option>
</select>
<h3>{{fruit}}</h3>
<!-- 选择多个 -->
<select name="a" v-model="fruits" multiple>
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="grape">grape</option>
</select>
<h3>{{fruits}}</h3>
<label :for="item" v-for="item in originFruits">
<input
type="checkbox"
:id="item"
:value="item"
v-model="hobbies"
/>{{item}}
</label>
<h2>{{hobbies}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
fruit: "apple",
fruits: [],
originFruits: ["a", "b", "c", "d", "e"],
hobbies: [],
},
});
</script>
<div id="app">
<!-- 修饰符 -->
<!--
lazy
默认情况下,v-model实在input事件中同步输入框的数据的,也就是说一旦有数据发生改变对应的data中的数据就会自动发生改变
lazy修饰符可以让数据再失去焦点或者回车时才会更新
-->
<input type="text" v-model.lazy="message" />
{{message}}
<br />
<!--
number
默认情况下,再输入框中无论我们输入的时字母还是数字,都会被当作字符串类型处理
但是如果我们希望处理的是数字类型,那么最好直接将内容当作数字处理
number修饰符可以让输入框中输入的内容自动转成数字类型
-->
<input type="number" v-model.number="age" />
{{age}} {{typeof age}}
<br />
<!--
trim
如果输入的内容首尾有很多空格,通常我们希望将其取出
trim修饰符可以过滤内容左右两边的空格
-->
<input type="text" v-model.trim="name" />
{{name}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "hello",
age: "",
name: "",
},
});
</script>
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnC = Vue.extend({
template: `标题
内容
`,
});
// 2.注册组件
Vue.component("my-cpn", cpnC);
const app = new Vue({
el: "#app",
data: {},
});
</script>
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 my-cpn
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
。
创建组件构造器对象
template
中是组件的DOM元素内容。
注册组件
Vue.component
。components:{cpnc:cpnc}
。全局组件,可以在多个vue实例中使用,类似于全局变量。使用Vue.component('my-cpn', cpnc)
方式注册,直接使用
调用。my-cpn
是全局组件的名字,cpnc
是定义的组件对象。
局部组件,只能在当前vue实例挂载的对象中使用,类似于局部变量,有块级作用域。
这部分我的全局组件没有运行成功,还在寻找原因,如果大家有找到错误部分的话敲我一下,谢谢啦~
暂将目前代码附如下
<my-cpn></my-cpn>
<cpn></cpn>
<div id="app">
<my-cpn></my-cpn>
<cpn></cpn>
</div>
<div id="app2">
<my-cpn></my-cpn>
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 创建组件构造器
const cpnC1 = Vue.extend({
template: `全局
`,
});
const cpnC2 = Vue.extend({
template: `局部
`,
});
// 注册组件(全局组件,意味着可以再多个Vue的示例下面使用)
Vue.component("my-cpn", cpnC1);
const app = new Vue({
el: "#app",
data: {},
// 局部组件注册
components: {
cpn: cpnC2,
},
});
</script>
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建第一个组件
const cpnC1 = Vue.extend({
template: `
标题1
内容1
`,
});
const cpnC2 = Vue.extend({
template: `
标题2
内容2
`,
components: {
cpn1: cpnC1,
},
});
const app = new Vue({
el: "#app",
data: {},
components: {
cpn2: cpnC2,
},
});
</script>
上述代码中定义了两个组件对象cpn1
和cpn2
,在组件cpn2
中使用局部组件注册了cpn1
,并在template
中使用了注册的cpn1
,然后在vue实例中使用注册了局部组件cpn2
,在vue实例挂载的div中调用了cpn2
,cpn2
与cpn1
形成父子组件关系。
注意:组件就是一个vue实例,vue实例的属性,组件也可以有,例如data、methods、computed等。
<div id="app">
<!-- 使用组件 -->
<my-cpn></my-cpn>
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 全局组件注册的语法糖
// 1.创建组件构造器对象
// const cpnC = Vue.extend();
// 2.注册组件
Vue.component("my-cpn", {
template: `标题
内容
`,
});
// 3.使用组件
const app = new Vue({
el: "#app",
data: {},
components: {
cpn: {
template: `标题2
内容2
`,
},
},
});
</script>
注册组件时候可以不实例化组件对象,直接在注册的时候实例化。{}
就是一个组件对象。
<div id="app">
<cpn></cpn>
</div>
<!-- 1.script类型,注意类型必须是text/x-template -->
<!-- <script type="text/x-template" id="cpn">
<div>
<h2>标题</h2>
<p>内容</p>
</div>
</script> -->
<template id="cpn">
<div>
<h2>{{title}}</h2>
<p>内容</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("cpn", {
template: "#cpn",
data() {
return {
title: "abc",
};
},
});
const app = new Vue({
el: "#app",
});
</script>
组件中的数据存放问题
<div id="app">
<cpn></cpn>
</div>
<!-- 1.script类型,注意类型必须是text/x-template -->
<!-- <script type="text/x-template" id="cpn">
<div>
<h2>标题</h2>
<p>内容</p>
</div>
</script> -->
<template id="cpn">
<div>
<h2>{{title}}</h2>
<p>内容</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("cpn", {
template: "#cpn",
data() {
return {
title: "abc",
};
},
});
const app = new Vue({
el: "#app",
});
</script>
组件中的data为什么是函数
这部分可以查看Vue官方文档,我觉得讲的很清楚,举的例子也很好玩,跟视频中老师的例子其实是一个
<!-- 组件示例对象 -->
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
当前计数:
<button @click="decrement">-</button>
{{counter}}
<button @click="increment">+</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("cpn", {
template: "#cpn",
// 闭包,变量私有化
data() {
return {
counter: 0,
};
},
methods: {
decrement() {
this.counter--;
},
increment() {
this.counter++;
},
},
});
const app = new Vue({
el: "#app",
});
</script>
v-bind是 不支持使用驼峰标识的,例如cUser
要改成c-User
。
父传子
注意:类型是对象或者数组时,默认值必须是一个函数
<div id="app">
<cpn v-bind:cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
{{cmovies}}
<br>
{{cmessage}}
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpnC = Vue.extend({
template: `#cpn`,
// props : ['cmovies', 'cmessage']
props: {
// 类型限制
// cmovies : Array,
// cmessage : String
// 提供一些默认值
cmessage: {
type: String,
default: "aaaaaaa", // 当没有传值时的默认值
required: true, // 在使用时,cmessage是必传值
},
// 类型是对象或者数组时,默认值必须是一个函数
cmovies: {
type: Array,
default() {
return [];
},
},
},
});
const app = new Vue({
el: "#app",
data: {
message: "Hello",
movies: ["1", "2", "3"],
},
components: {
cpn: cpnC,
},
});
</script>
子传父
<div id="app">
<cpn @itemclick="cpnClick"></cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
data() {
return {
categories: [
{ id: "aaa", name: "热门推荐" },
{ id: "bbb", name: "手机数码" },
{ id: "ccc", name: "家用家电" },
{ id: "ddd", name: "电脑办公" },
],
};
},
methods: {
btnClick(item) {
// 发射
this.$emit("itemclick", item);
},
},
};
const app = new Vue({
el: "#app",
components: {
cpn,
},
methods: {
cpnClick(item) {
console.log("itemClick", item);
},
},
});
</script>
1.在子组件中定义一个方法btnClick(item)
,使用$emit
,'itemclick’是事件名,item
是传过去的值。
methods: {
btnClick(item) {
this.$emit('itemclick', item)
}
},
2.在子组件中监听点击事件并回调此方法
3.在父组件中定义一个方法cpnClcik(item)
methods: {
cpnClcik(item) {
console.log('cpnClick'+item.name);
}
},
4.并在父组件(vue实例)中调用
(不写参数默认传递btnClick的item ),父组件监听事件名为itemclick
的子组件传过来的事件。
组件间通信案例
<div id="app">
<cpn
:number1="num1"
:number2="num2"
@num1change="num1Change"
@num2change="num2Change"
></cpn>
</div>
<template id="cpn">
<div>
<h2>props : {{number1}}</h2>
<h2>data : {{dnumber1}}</h2>
<input type="text" :value="dnumber1" @input="num1input" />
<h2>props : {{number2}}</h2>
<h2>data : {{dnumber2}}</h2>
<input type="text" :value="dnumber2" @input="num2input" />
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
methods: {
num1change(value) {
this.num1 = parseInt(value);
},
num2change(value) {
this.num2 = parseInt(value);
},
},
props: {
number1: Number,
number2: Number,
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2,
};
},
methods: {
num1input(event) {
this.dnumber1 = event.target.value;
this.$emit("num1change", this.dnumber1);
},
num2input(event) {
this.dnumber2 = event.target.value;
this.$emit("num2change", this.dnumber2);
},
},
};
const app = new Vue({
el: "#app",
data: {
num1: 1,
num2: 2,
},
methods: {
num1Change(value) {
this.num1 = value;
},
num2Change(value) {
this.num2 = value;
},
},
components: {
cpn,
},
});
</script>