- vue是MVVM框架,MVVM就是我们常说的双向数据绑定,M表示model,V表示view,在MVVM的框架中,model的改变会影响视图view,view视图的改变会反过来影响model.
vm.$data/vm.$attrs/vm.$el/vm.$emit/vm.$forceUpdate/vm.$nextTick/vm.$options/vm.$parent/vm.$props/vm.$refs/vm.$root/vm.$slots/vm.$watch等
一、绑定数据
<template>
<div>
<h1>{{ message }}</h1>
<p>绑定对象:{{ userinfo.username }}--{{ userinfo.age }}</p>
<p>绑定html: <span v-html="h2"></span></p>
</div>
</template>
<script>
export default {
data() {
return {
message: "vue",
userinfo: {
username: "张三",
age: "20",
},
h2: "<h2>vue 我是一个html标签</h2>"
}
}
}
</script>
二、绑定属性
<template>
<div>
<img v-bind:src="logoSrc" alt="logoSrc" />
<br />
<img :src="logoSrc" alt="logoSrc" />
<br />
<div title="vue">鼠标放上去试试1</div>
<br />
<div :title="title">鼠标放上去试试2</div>
</div>
</template>
<script>
export default {
data() {
return {
logoSrc: "https://www.itying.com/themes/itying/images/logo.gif",
title: "自定义属性值"
}
}
}
</script>
三、绑定动态属性
<template>
<div>
<a v-bind:[myHref]="'http://www.baidu.com'">跳转百度</a>
<br />
<a :[myHref]="myLink">跳转到myLink</a>
</div>
</template>
<script>
export default {
data() {
return {
myHref: "href",
myLink: "http://www.itying.com"
}
}
}
</script>
四、循环遍历数组
<template>
<div>
<ul>
<li v-for="(item, index) in list1" :key="index">
{{ item }}--{{ index }}
</li>
</ul>
<br />
<ul>
<li v-for="(item, index) in list2" :key="index">
{{ item.title }}
</li>
</ul>
<br />
<br />
<ul>
<li v-for="(item, index) in list3" :key="index">
{{ item.cate }}
<ol>
<li v-for="(i, k) in item.list" :key="k">
{{ i.title }}
</li>
</ol>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
list1: ["张三", "李四", "王五"],
list2: [{
title: "张三111",
},
{
title: "张三2222",
},
{
title: "张三3333",
},
{
title: "张三444",
},
],
list3: [{
cate: "国内新闻",
list: [{
title: "国内新闻11111",
},
{
title: "国内新闻2222",
},
],
},
{
cate: "国际新闻",
list: [{
title: "国际新闻11111",
},
{
title: "国际新闻2222",
},
],
},
],
}
}
}
</script>
五、循环遍历对象
<template>
<div>
<ul>
<li v-for="(value, attr, index) in myObject" :key="index">
{{ attr }}---{{ value }}--{{ index }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
myObject: {
title: "study Vue",
author: "liang",
publishedAt: "2021-05-22",
}
}
}
}
</script>
六、绑定事件
// event, $event
// 事件修饰符:stop, prevent, capture, self, once, passive
// 按键修饰符:enter, tab, delete, esc, up, down, left, right
// 鼠标修饰符:left, right, middle
// 精确修饰符:exact
<template>
<div>
<h3>{{title}}</h3>
<button v-on:click="setTitle('111')">设置Title的值1</button>
<br>
<br>
<button v-on:click="setTitle('2222')">设置Title的值2</button>
<button v-on:click="changeClass()">改变class</button>
<br />
<button @click="changeClass()">改变class</button>
<br />
<div :class="myClass"></div>
<button @click="run()">执行run方法实现方法调用方法</button>
<br>
<button data-aid="123" @click="eventFn($event)">事件对象</button>
<br>
<br>
<button @click="warn('传入的参数', $event)">
Submit
</button>
<br>
<br>
<button @click="one(),two(),changeClass()">
点击按钮一次执行多个方法
</button>
<br>
<br>
<a href="http://www.baidu.com" target="_blank" @click="afn1($event)">跳转链接1</a>
<br><br>
<a href="http://www.baidu.com" target="_blank" @click.prevent="afn2()">跳转链接2</a>
<br>
<br>
<input type="text" @keyup="doSearch1($event)">
<br> <br>
<input type="text" @keyup.enter="doSearch2()" />
</div>
</template>
<script>
export default {
data() {
return {
myClass: "red",
msg: "学习vue",
title: "我是一个标题"
}
},
methods: {
getMsg() {
alert(this.msg)
},
setTitle(data) {
this.title = data;
},
changeClass() {
this.myClass = "blue";
},
run() {
this.changeClass()
},
eventFn(e) {
console.log(e);
e.srcElement.style.background = "red";
//获取自定义属性
console.log(e.srcElement.dataset.aid);
// e.preventDefault();
// e.stopPropagation();
},
warn(message, event) {
console.log(event);
if (event) {
event.preventDefault()
}
alert(message)
},
one() {
console.log("one");
},
two() {
console.log("two");
},
afn1(e) {
e.preventDefault();
},
afn2() {
},
doSearch1(e) {
console.log(e)
console.log(e.keyCode)
if (e.keyCode == 13) {
alert("按了回车键")
}
},
doSearch2() {
alert("按了回车键")
},
},
}
</script>
七、class、style绑定多个动态属性
<template>
<div>
<div :class="{ active: isActive, red: isRed }">div</div>
<div class="blue" :class="{ active: isActive }">div</div>
<br />
<div :class="[errorClass, baseClass]">div</div>
<br />
<div :class="[flag ? baseClass : errorClass]">三目运算绑定class</div>
<h2>绑定多个style</h2>
<br>
<div :style="'color:'+color">
绑定style
</div>
<br>
<div :style="{'color':activeColor,'fontSize':fontSize}">
绑定多个style
</div>
<br>
<div :style="styleObject">
绑定多个style
</div>
<br>
<br>
<div :style="[baseStyles,orangeStyle]">
绑定多个style
</div>
<br>
<ul>
<li v-for="(item,index) in list" :key="index" :class="{'aaa':index==0,'bbb':index==1}">
{{item}}
</li>
</ul>
<br>
<ul>
<li v-for="(item,index) in list" :key="index" :style="[index==0?styleRed:null,index==1?styleBlue:null]">
{{item}}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
isActive: true,
isRed: false,
errorClass: "error",
baseClass: "base",
flag: true,
color: "red",
activeColor: "blue",
fontSize: "20px",
styleObject: {
color: 'red',
fontSize: '43px'
},
baseStyles: {
"100px",
height: "100px",
fontSize: '18px'
},
orangeStyle: {
background: "orange"
},
list: ['张三', '李四', '王五', '张三1', '李四1', '王五1'],
styleRed: {
color: 'red',
},
styleBlue: {
color: 'blue',
},
}
},
methods: {
changeClass() {
this.myClass = "blue";
},
},
}
</script>
<style scope>
.base {
300px;
height: 300px;
}
.active {
display: block;
font-size: 30px;
color: orange;
}
.error {
background: orange;
font-size: 30px;
color: red;
}
.red {
background: red;
100px;
height: 100px;
}
.blue {
background: blue;
100px;
height: 100px;
}
.aaa {
color: red;
}
.bbb {
color: blue;
}
</style>
八、ref和双向数据绑定
// input, textarea, checkbox, radio, select
// 修饰符 lazy, number, trim
<template>
<div>
<h2>人员登记系统</h2>
<!-- <div class="people_list">
<ul>
<li>姓 名: <input type="text" id="username" /></li>
<li>年 龄: <input type="text" ref="age" /></li>
</ul>
<button @click="doSubmit()" class="submit1">获取表单的内容</button>
</div> -->
<div class="people_list">
<ul>
<li>姓 名: <input type="text" v-model="userinfo.username" /></li>
<li>年 龄: <input type="text" v-model="userinfo.age" /></li>
<li>性 别:
<input type="radio" name="sex" id="sex1" value="1" v-model="userinfo.sex"> <label for="sex1">男</label>
<input type="radio" name="sex" id="sex2" value="2" v-model="userinfo.sex"> <label for="sex2">女</label>
</li>
<li> 城 市:
<select v-model="userinfo.city">
<option v-for="(item,index) in userinfo.cityList" :key="index" :value="item">{{item}}</option>
</select>
</li>
<li> 爱 好:
<span v-for="(item,index) in userinfo.hobby" :key="index">
<input type="checkbox" :id="'ch_'+index" v-model="item.checked" />
<label :for="'ch_'+index">{{item.title}}</label>
</span>
</li>
<li> 备注:
<textarea cols="30" rows="4" v-model="userinfo.mark"></textarea>
</li>
</ul>
<button @click="doSubmit()" class="submit">获取表单的内容</button>
<br>
<br>
<pre>{{userinfo}}</pre>
</div>
</div>
</template>
<script>
export default {
name: "Register",
props: {},
data() {
return {
username: "zhangsan",
userinfo: {
username: "",
age: "",
sex: "1",
cityList: ["北京", "上海", "深圳"],
city: "上海",
hobby: [
{
title: "吃饭",
checked: false
},
{
title: "睡觉",
checked: false
},
{
title: "写代码",
checked: true
}
],
mark: ""
}
}
},
methods: {
// doSubmit1() {
// // 原生js
// var usernameObj = document.querySelector("#username")
// console.log(usernameObj.value)
// /**
// * 1、定义ref <iniput type="text" ref="age"
// * 2、this.$refs.名称
// */
// console.log(this.$refs)
// console.log(this.$refs.age.value)
// }
doSubmit() {
console.log(this.userinfo)
}
}
}
</script>
<style scope>
ul {
list-style-type: none;
}
h2 {
text-align: center;
}
.people_list {
400px;
margin: 40px auto;
padding: 40px;
border: 1px solid #eee;
}
.people_list li {
height: 50px;
line-height: 50px;
}
.submit {
float: right;
margin-top: 10px;
}
</style>
九、JavaScript表达式、条件判断、计算属性、watch侦听
computed 和 method 都能实现的一个功能,建议使用 computed,因为有缓存
computed 和 watcher 都能实现的功能,建议使用 computed 因为更加简洁
<template>
<div>
<h3>1、Vue3.x模板中使用JavaScript表达式</h3>
<div>
{{ a + 3 }}
<br />
{{ a * 3 }}
<br />
{{ a - 3 }}
<br />
{{ flag ? "this is true" : "this is false" }}
<br />
{{ flag ? name1 : name2 }}
<br />
{{ message.split("").reverse().join("") }}
</div>
<h3>2、 v-if v-else v-else-if v-show</h3>
<div>
<div v-if="flag == true">this is true</div>
<br>
<span v-if="flag == true">this is true</span>
<span v-else>this is false</span>
<br>
<span v-if="Math.random()>0.5">
大于0.5
</span>
<span v-else>
小于0.5
</span>
<br>
<div v-if="type=='A'">A</div>
<div v-else-if="type=='B'">B</div>
<div v-else-if="type=='C'">C</div>
<div v-else>Not A/B/C</div>
<br>
<template v-if="flag">
<hr>
<span>这是一个sapn</span>
<div>这是一个div</div>
<hr>
</template>
</div>
<h3>4、 计算属性</h3>
<div>
{{reverseMsg}}
<br>
<button @click="setMsg()">改变msg的值</button>
<br>
<hr>
<input type="text" v-model="keyword" placeholder="请输入关键词" />
<ul>
<li v-for="(item,index) in searchData" :key="index">{{item}}</li>
</ul>
</div>
<h3>5、 watch监听数据变化</h3>
<div>
<input type="text" v-model="firstName" placeholder="firstName">
<br>
<input type="text" v-model="lastName" placeholder="lastName">
<br>
{{fullName}}
<br>
</div>
</div>
</template>
<script>
export default {
data() {
return {
a: 12,
flag: false,
message: "三国演义",
name1: "张三",
name2: "李四",
type: "N",
listData: ["apple", "banana", "orange", "pear"],
keyword: "",
firstName: "",
lastName: "",
fullName: ""
}
},
methods: {
setMsg() {
this.message = "大家好"
}
},
computed: {
reverseMsg() {
return this.message.split("").reverse().join("")
},
searchData() {
var tempArr = []
this.listData.forEach((value) => {
if (value.indexOf(this.keyword) !== -1 && this.keyword !== "") {
tempArr.push(value)
}
})
console.log(tempArr)
return tempArr
}
// fullName() {
// return this.firstName + " " + this.lastName
// }
},
watch: {
firstName: function (value) {
this.fullName = value + " " + this.lastName
},
lastName: function (value) {
this.fullName = this.firstName + " " + value
}
}
}
</script>
<style scope>
</style>
十、插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>study</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// slot 插槽
// slot 中使用的数据,作用域的问题
// 父模版里调用的数据属性,使用的都是父模版里的数据
// 子模版里调用的数据属性,使用的都是子模版里的数据
// 具名插槽
const app = Vue.createApp({
template: `
<layout>
<template v-slot:header>
<div>header</div>
</template>
<template v-slot:footer>
<div>footer</div>
</template>
</layout>
`
});
app.component('layout', {
template: `
<div>
<slot name="header"></slot>
<div>content</div>
<slot name="footer"></slot>
</div>
`
// 或 <slot #header></slot>
});
const vm = app.mount('#root');
</script>
</html>
作用域插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>study</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 作用域插槽
const app = Vue.createApp({
template: `
<list v-slot="{item}">
<div>{{item}}</div>
</list>
`
});
app.component('list', {
data() {return {list: [1, 2, 3]}},
template: `
<div>
<slot v-for="item in list" :item="item" />
</div>
`
});
const vm = app.mount('#root');
</script>
</html>
十一、异步组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>study</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 动态组件: 根据数据的变化,结合 compoent 这个标签,来随时动态切换组件的现实
// 异步组件: 是异步执行某些组件的逻辑,这叫做异步组件
const app = Vue.createApp({
template: `
<div>
<common-item />
<async-common-item />
</div>
`
});
app.component('common-item', {
template: `<div>hello world</div>`
});
app.component('async-common-item', Vue.defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
template: `<div>this is an async component</div>`
})
}, 4000)
})
}))
const vm = app.mount('#root');
</script>
</html>
十二、其它
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>study</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// v-once 让某个元素标签只渲染一次
// ref 实际上是获取 Dom 节点 / 组件引用 的一个语法
// provide / inject
const app = Vue.createApp({
data() {
return { count: 1}
},
provide() {
return {
count: this.count,
}
},
template: `
<div>
<child :count="count" />
<button @click="count += 1">Add</button>
</div>
`
});
app.component('child', {
template: `<child-child />`
});
app.component('child-child', {
inject: ['count'],
template: `<div>{{count}}</div>`
});
const vm = app.mount('#root');
</script>
</html>
十三、
持续更新中......