Vue.js安装
这里我们使用方式二:
去官网,下载vue.js(开发版本)
使用webstorm新建项目,然后新建js文件夹,把刚才下载的vue.js放到js文件夹下
修改数据
第一个vue代码
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">{{message}}div>
<script src="../js/vue.js">script>
<script>
//let(变量) const(常量)
//new Vue,说明有一个function Vue()
//声明式编程
const app = new Vue({
//用于挂载要管理的元素
el:'#app',
//定义数据
data:{
message:'你好呀,李银河!'
}
})
//以上代码使用js实现(命令式编程)
//1、创建div元素
//2、定义一个变量叫message
//3.将message变量放在前面的div元素中
//4.修改message数据:
//5.将修改后的数据再次替换到div元素
script>
body>
html>
vue列表展示
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h1>{{movies[0]}}h1>
<ul>
<li v-for="item in movies">{{item}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
movies: ['龙门飞甲','芳华','剑雨','盗梦空间']
}
})
script>
body>
html>
响应式添加数据
vue计数器实列
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>当前计数:{{counter}}h2>
<button v-on:click="counter++">+button>
<button v-on:click="counter--">-button>
<button v-on:click="add">+button>
<button v-on:click="sub">-button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
//定义方法,函数
methods: {
add: function(){
console.log("add被执行了!")
//注意,在函数里使用data中变量时,不能直接使用变量名,如果使用变量名它就会默认去找全局变量
//使用data中的变量时,因为这些变量都是在Vue对象中,可以使用Vue的实列app调用变量,但最推荐的方式是使用this(当前对象)
this.counter++
},
sub: function(){
console.log("sub被执行了!")
this.counter--
}
}
})
script>
body>
html>
语法糖:v-on:click等价于@click
Vue中的MVVM
计数器中的MVVM
另外的写法:结构更加清晰(使用了代理)
vue中的参数:options
el:
data:组件的时候必须传Function
function:函数:全局的function就是函数
方法:与类挂钩,类中的function是方法,即方法与类的实列挂钩
Vue的声明周期:
回调函数:
Vue自动回调函数
一般在created中做一些网络请求
代码规范:缩进两个空格
cli->.editconfig
webstorm中设置
编写自己的模板
<div id="app">
{{message}}
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
复制以上代码,点击设置->Editor->Live Templates->Vue
点击+号
点击Define
点击HTML,点击apply,点击应用,以后在html中输入vue后tab键即可弹出我们刚才定义的模板。、
tab键可以自定义为自己喜欢的方式
基本语法
模板语法
插值操作:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{message}}h2>
<h2>{{message}},李银河h2>
<h2>{{firstName + lastName}}h2>
<h2>{{firstName + ' ' + lastName}}h2>
<h2>{{firstName}} {{lastName}}h2>
<h2>{{counter * 2}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
firstName: 'kobe',
lastName: 'bryant',
counter: 100
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{message}}h2>
<h2 v-once>{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
v-once
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{url}}h2>
<h2 v-html="url">h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
url: '百度一下'
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2> {{message}}h2>
<h2 v-text="message">h2>
<h2 v-text="message">,李银河h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
第三个v-text后的,李银河被覆盖了
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{message}}h2>
<h2 v-pre>{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
v-cloak:cloak(斗篷)
v-cloak加上css代码可以防止网络抖动时js代码执行缓慢导致的显示{{message}},而不是输出内容的情况,如模拟网络延时时
这是,就会出现上面的情况,1s后js解析完成,才能正常显示,使用v-cloak指令,让网络延时时什么也不显示
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
/*设置v-cloak的样式*/
[v-cloak]{
display: none
}
style>
head>
<body>
<div id="app">
<h2 v-cloak>{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
//设置网络延时1秒后执行function函数
//v-cloak:在vue解析之前,div中有一个属性,v-cloak
//在vue解析完成后,div中没有属性v-cloak(即vue解析完成后会自动删除v-cloak-->
setTimeout(function(){
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
},1000)
script>
body>
html>
这时,vue解析延时时,会展示空白(即什么也不展示)
v-bind:绑定属性,即把数据绑定到属性中
使用mustache语法,直接在src中显示{{imgUrl}}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<img v-bind:src="imgUrl" alt="">
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
//图片地址,网上随便找的
imgUrl: 'https://scpic.chinaz.net/files/pic/pic9/202106/apic33584.jpg'
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<img v-bind:src="imgUrl" alt="">
<a v-bind:href="aHref">百度一下a>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
//图片地址,网上随便找的
imgUrl: 'https://scpic.chinaz.net/files/pic/pic9/202106/apic33584.jpg',
aHref: 'http:www.baidu.com'
}
})
script>
body>
html>
v-bind的语法糖:v-bind等价于:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
.actives{
color: red;
}
style>
head>
<body>
<div id="app">
<h2 :class="active">{{message}}h2>
<h2 class="title" v-bind:class="{actives: isActive, line: isLine}">{{message}}h2>
<button @click="btnClick">改变颜色button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
active: 'actives',
isActive: true,
isLine: true
},
methods: {
btnClick: function(){
this.isActive = !this.isActive
}
}
})
script>
body>
html>
{}对象使用函数返回
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
.actives{
color: red;
}
style>
head>
<body>
<div id="app">
<h2 class="title" :class="{actives: isActive, line: isLine}">{{message}}h2>
<h2 class="title" :class="getClass()">{{message}}h2>
<button @click="btnClick">改变颜色button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
isActive: true,
isLine: true
},
methods: {
btnClick: function(){
this.isActive = !this.isActive
},
getClass: function(){
return {actives: this.isActive, line: this.isLine}
}
}
})
script>
body>
html>
数组语法:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2 class="title" :class="['actives','line']">{{message}}h2>
<h2 class="title" :class="[class1,class2]">{{message}}h2>
<h2 class="title" :class="getClass()">{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
class1: 'actives',
class2: 'line'
},
methods: {
getClass: function(){
return [this.class1, this.class2]
}
}
})
script>
body>
html>
效果是一样的
作业需求:
点击列表中的某一项,那个该项文字变成红色:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in movies">{{index + '-' + item}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
movies: ['海王','海尔兄弟','火影忍者','进击的巨人']
}
})
script>
body>
html>
v-bind动态绑定style
对象语法:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2 :style="{'font-size': '50px'}">{{message}}h2>
<h2 :style="{fontSize: '50px'}">{{message}}h2>
<h2 :style="{'fontSize': '50px'}">{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
效果一样:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2 :style="{'font-size': '50px'}">{{message}}h2>
<h2 :style="{fontSize: '50px'}">{{message}}h2>
<h2 :style="{'fontSize': '50px'}">{{message}}h2>
<h2 :style="{fontSize: finalSize}">{{message}}h2>
<h2 :style="{fontSize: finalSize01 + 'px'}">{{message}}h2>
<h2 :style="{fontSize: finalSize01 + 'px', color: finalColor}">{{message}}h2>
<h2 :style="{fontSize: finalSize01 + 'px', background: finalColor}">{{message}}h2>
<h2 :style="getStyles()">{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
finalSize: '100px',
finalSize01: 100,
finalColor: 'red'
},
methods: {
getStyles: function(){
return {fontSize: this.finalSize01 + 'px', background: this.finalColor};
}
}
})
script>
body>
html>
数组语法:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2 :style="[baseStyle, fontSize]">{{message}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
baseStyle: {background: 'red'},
fontSize: {fontSize: '50px'}
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{firstName}} {{lastName}}h2>
<h2>{{firstName + ' ' + lastName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
}
})
script>
body>
html>
上面的代码弊端:如果要写多次,就需要拼接多次,工作量大
解决办法一:使用方法
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{firstName}} {{lastName}}h2>
<h2>{{firstName + ' ' + lastName}}h2>
<h2>{{getFullName()}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
},
methods: {
getFullName(){
return this.firstName + ' ' + this.lastName
}
}
})
script>
body>
html>
解决办法二:使用计算属性:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{firstName}} {{lastName}}h2>
<h2>{{firstName + ' ' + lastName}}h2>
<h2>{{getFullName()}}h2>
<h2>{{fullName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
},
methods: {
getFullName(){
return this.firstName + ' ' + this.lastName
}
},
computed: {
//类似于函数的定义,只不过这里使用的名词形式的函数名,即名字尽量使用名词,定义后是把它当作一个属性去使用,而不是函数
fullName: function(){
return this.firstName + ' ' + this.lastName
}
}
})
script>
body>
html>
计算属性的应用场景:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>总价格:{{totalPrice}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 110, name: 'Unix编程艺术', price: 119
},
{
id: 112, name: 'java编程艺术', price: 120
},
{id: 113, name:'深入计算机原理', price: 130},
{id: 114, name: '代码大全', price: 140},
{id: 115, name: '现代操作系统', price: 88}
]
},
//使用计算属性,计算总价格
computed: {
totalPrice: function(){
let result = 0
for(let i=0; i<this.books.length; i++){
result += this.books[i].price
}
//或者
/*for(let book of this.books){
result += book.price
}*/
return result;
}
}
})
script>
body>
html>
计算属性,在html中多次调用时,只执行一次,而函数没调用一次就执行一次,所以计算属性的执行效率更高。
Vue Day01回顾:
一、邂逅Vuejs
1.1.认识vuejs
1.2.安装vue
1.3.vue初体验
Hello vuejs
vue列表展示
Vue计数器小案例
1.4.vue中的MVVM
1.5.创建vue时,options可以放哪些东西
二、插值语法
三、v-bind
3.1.v-bind绑定基本属性
3.2.v-bind动态绑定class
3.3.v-bind动态绑定style
四、计算属性
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{fullName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
//函数形式的写法
/*fullName: function(){
return this.firstName + ' ' + this.lastName;
}*/
//setter和getter写法 属性名:{} {}表示一个对象,对象中setter和getter方法
fullName: {
set: function(){
},
get: function(){
//当我们使用计算属性的属性名时,本质就是来调用这个get方法
return this.firstName + ' ' + this.lastName;
}
}
}
})
script>
body>
html>
注意:计算属性一般是不希望设置值的,即计算属性一般没有set方法,是一个只读属性
因为删除了set方法,所以计算属性有一种更为简洁的写法,如下:(即我们之前用的方法)
fullName: function(){
}
给计算属性赋值:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{fullName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
//函数形式的写法
/*fullName: function(){
return this.firstName + ' ' + this.lastName;
}*/
//setter和getter写法 属性名:{} {}表示一个对象,对象中setter和getter方法
fullName: {
set: function(newValue){
//console.log('-----', newValue)
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[1]
},
get: function(){
//当我们使用计算属性的属性名时,本质就是来调用这个get方法
return this.firstName + ' ' + this.lastName;
}
}
}
})
script>
body>
html>
计算属性的缓存
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3>{{firstName}} {{lastName}}h3>
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<h3>{{getFullName()}}h3>
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
<h3>{{fullName}}h3>
<h3>h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lemon',
lastName: 'Time'
},
//methods
methods: {
getFullName: function(){
console.log('getFullName')
return this.firstName + ' ' + this.lastName
}
},
computed: {
fullName: function(){
console.log('fullName')
return this.firstName + ' ' + this.lastName
}
}
})
script>
body>
html>
可以看到methods打印了4次getFullName,而计算属性值打印了1次fullName,说明计算属性值执行了一次,之后再使用计算属性时,它直接把结果返回回来,而不会再去执行里面的操作(即直接返回return后的结果,里面的细节都不会再执行一次),但是返回值的计算表达式中的值发生了变化,计算属性还是会重新执行一次的,以保证结果的正确性
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button>按钮1button>
<button>按钮2button>
<button>按钮3button>
<button>按钮4button>
<button>按钮5button>
<script>
//1.变量作用域:变量在什么范围内起作用
{
var name = 'why';
console.log(name)
}
//name在块外也起作用
console.log(name)
// 没有块级作用域引起的问题
var func;
if(true){
var name = 'why';
func = function(){
console.log(name);
}
}
//在调用func前修改了name的值
name = 'Kobe';
//打印的name不是我们希望的why,而是Kobe
func()
//没有块级作用域引起的问题: for的块级
var btns = document.getElementsByTagName('button')
//当我们点击按钮时,几乎都会输出'第5个按钮被点击了‘,原因跟上面的列子差不多,我们在事件监听的函数中使用的i是外部的i,由于
//外部的i是增加事件监听的,执行的很快,于是i就被变为了5,当我们点击按钮的时候,执行事件监听的方法,于是i还是5
for(var i = 0; i < btns.length; i++){
btns[i].addEventListener('click', function(){
console.log('第' + i + '个按钮被点击');
})
}
script>
body>
html>
以前为了解决这个问题,需要使用闭包
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button>按钮1button>
<button>按钮2button>
<button>按钮3button>
<button>按钮4button>
<button>按钮5button>
<script>
//函数的作用域
var name = 'why'
function abc(name){
console.log(name)
}
//我们这里只是改变了函数外name的值,并不会影响形参的name,形参的name是我们传什么就是什么
name = 'Kobe'
abc('hello')
//没有块级作用域引起的问题: for的块级
var btns = document.getElementsByTagName('button')
//使用闭包解决这个问题:
//为什么闭包能解决这个问题:因为函数是一个作用域
for(var i = 0; i < btns.length; i++){
(function(i){
btns[i].addEventListener('click', function(){
console.log('第' + i + '个按钮被点击');
})
})(i)
}
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button>按钮1button>
<button>按钮2button>
<button>按钮3button>
<button>按钮4button>
<button>按钮5button>
<script>
//函数的作用域
var name = 'why'
function abc(name){
console.log(name)
}
//我们这里只是改变了函数外name的值,并不会影响形参的name,形参的name是我们传什么就是什么
name = 'Kobe'
abc('hello')
//没有块级作用域引起的问题: for的块级
var btns = document.getElementsByTagName('button')
//使用闭包解决这个问题:
//为什么闭包能解决这个问题:因为函数是一个作用域
for(var i = 0; i < btns.length; i++){
(function(num){
btns[i].addEventListener('click', function(){
console.log('第' + num + '个按钮被点击');
})
})(i)
}
script>
body>
html>
ES6之前因为if和for都没有块级作用域的概念,所以在很多时候,我们必须借助于function的作用域来解决外面变量的问题。这个function一般是匿名function
使用let解决块级作用域:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button>按钮1button>
<button>按钮2button>
<button>按钮3button>
<button>按钮4button>
<button>按钮5button>
<script>
const btns = document.getElementsByTagName('button');
for(let i=0;i<btns.length;i++){
btns[i].addEventListener('click', function(){
console.log('第' + i + '个按钮被点击');
})
}
script>
body>
html>
在es6中,优先使用const,只有需要改变某一个变量是,才使用let
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script>
//正常定义对象
// const obj = new Object()
//字面量写法:{}就表示字面量
//原来的写法
/*const obj = {
name: 'why',
age: 18,
run: function(){
console.log('在奔跑')
}*/
// 1.属性的增强写法
const name = 'why';
const age = 18;
const height = 180;
// ES5的写法
/*const obj = {
name: name,
age: age,
height: height
}*/
// ES6的写法,他会把变量名作为key,把变量的value作为value
const obj = {
name,
age,
height,
}
console.log(obj)
//2.函数的增强写法
//ES5的写法
/* const obj1 = {
run: function(){
},
eat: function(){
}*/
// ES6的写法
const obj1 = {
run(){
},
eat(){
}
}
script>
body>
html>
v-on:事件监听
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3>{{counter}}h3>
<button v-on:click="increment()">+button>
<button v-on:click="decrement()">-button>
<button v-on:click="increment">+button>
<button v-on:click="decrement">-button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment(){
this.counter++
},
decrement(){
this.counter--
}
}
})
script>
body>
html>
v-on的语法糖为:@
小括号可以省略的条件:事件监听中,调用的方法不需要传递参数
<button @click="btn3Click(123,event)">按钮6button>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<button @click="btn1Click()">按钮1button>
<button @click="btn1Click">按钮2button>
<button @click="btn2Click">按钮3button>
<button @click="btn2Click(123)">按钮4button>
<button @click="btn2Click()">按钮5button>
<button @click="btn3Click(123,event)">按钮6button>
<button @click="btn3Click(123,$event)">按钮6button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
event: 'Hello,你好'
},
methods: {
btn1Click(){
console.log('btn1Click');
},
btn2Click(param){
console.log('-----', param, '------');
},
btn3Click(param, event){
console.log('++++++', param,'event:', event);
}
}
})
script>
body>
html>
v-on的修饰符
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click="btnClick">按钮button>
div>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
}
}
})
script>
body>
html>
当我点击button中的按钮时,由于事件冒泡的存在,divClick也被点击了
阻止事件冒泡:stop
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
}
}
})
script>
body>
html>
prevent修饰符的使用:阻止默认事件的使用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
<br>
<form action="baidu">
<input type="submit" value="提交">
form>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
}
}
})
script>
body>
html>
点击按钮后,vue会自动提交:
我们不希望使用vue的默认提交,需要使用自己定义的提交:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
<br>
<form action="baidu">
<input type="submit" @click.prevent="submitClick" value="提交">
form>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
},
submitClick(){
console.log("submitClick");
}
}
})
script>
body>
html>
现在就只打印,不提交,如果要提交的话,可以自己定义自己的请求
监听某个键盘的某个键的点击:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
<br>
<form action="baidu">
<input type="submit" @click.prevent="submitClick" value="提交">
form>
<input type="text" @keyup="keyUp">
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
},
submitClick(){
console.log("submitClick");
},
keyUp(){
console.log("keyUp")
}
}
})
script>
body>
html>
当键按下抬起时就会被监听到
只监听某个特殊的按键,如回车键:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
<br>
<form action="baidu">
<input type="submit" @click.prevent="submitClick" value="提交">
form>
<input type="text" @keyup.enter="keyUp">
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
},
submitClick(){
console.log("submitClick");
},
keyUp(){
console.log("keyUp")
}
}
})
script>
body>
html>
这时只有按下回车键才会被监听到
.once只触发一次回调
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<div @click="divClick">
按钮
<button @click.stop="btnClick">按钮button>
div>
<br>
<form action="baidu">
<input type="submit" @click.prevent="submitClick" value="提交">
form>
<input type="text" @keyup.enter="keyUp">
<button @click.once="btn2Click">btn2button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
},
submitClick(){
console.log("submitClick");
},
keyUp(){
console.log("keyUp")
},
btn2Click(){
console.log("btn2Click");
}
}
})
script>
body>
html>
只有第一次点击才起作用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3 v-if="isShow">
<div>{{message}}div>
h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
isShow: true
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3 v-if="isShow">
<div>abcdiv>
<div>defdiv>
h3>
<h2 v-else>isShow为false时显示我h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
isShow: true
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3 v-if="score>=90">优秀h3>
<h3 v-else-if="score>=80">良好h3>
<h3 v-else>一般h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 99
}
})
script>
body>
html>
逻辑复杂的时候不建议这样做,如果逻辑复杂,最好使用计算属性的方式
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3>{{showLevel}}h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 99
},
computed: {
showLevel(){
if(this.score>=90){
return '优秀';
}
else if(this.score>=80){
return '良好';
}
else{
return '一般';
}
}
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<span v-if="isUser">
<label for="username">用户账号label>
<input type="text" id="username" placeholder="用户账号">
span>
<span v-else>
<label for="email">用户邮箱label>
<input type="text" id="email" placeholder="用户邮箱">
span>
<button @click="isUser=!isUser">切换类型button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
script>
body>
html>
当前小案列的小问题:例如我在用户账号界面输入了一些东西,突然想到应该用邮箱登录,于是切换到用户邮箱界面登录,但切换到用户邮箱叫界面时,在用户账号界面输入的账号也会携带过去,并不会清空
切换
vue底层原理:虚拟DOM,尽可能复用(只修改不同的地方)
需求:切换时清除之前的输入:使用key做标识,只用key相同时,才会复用,如果key不相同,vue就不会复用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<span v-if="isUser">
<label for="username">用户账号label>
<input type="text" id="username" placeholder="用户账号" key="username">
span>
<span v-else>
<label for="email">用户邮箱label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
span>
<button @click="isUser=!isUser">切换类型button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
script>
body>
html>
v-show:和v-if一样,也可以决定一个元素是否渲染
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3 v-if="isShow">{{message}}h3>
<h3 v-show="isShow">{{message}}h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好呀",
isShow: true
}
})
script>
body>
html>
当为true时,两个显示效果一样
修改为false:两个都不显示
查看html源码:
v-if在显示同时,html源码中也没有相应代码,v-show只是添加了一个行内样式:display:none
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in names">{{item}}li>
ul>
<ul>
<li v-for="(item, index) in names">{{index+1}}-itemli>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
names: ['why', 'who', 'what', 'whom', 'curry', 'lemon']
}
})
script>
body>
html>
在遍历的过程中,没有使用索引(下标值)
使用下标
v-for遍历对象:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li>{{info.name}}li>
<li>{{info.age}}li>
<li>{{info.height}}li>
ul>
<ul>
<li v-for="item in info">{{item}}li>
ul>
<ul>
<li v-for="(value, key) in info">{{key}} - {{value}}li>
ul>
<ul>
<li v-for="(value, key, index) in info">{{index}} - {{key}} - {{value}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: 'why',
age: 18,
height: 188
}
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in letters">{{item}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G']
}
})
script>
body>
html>
官方推荐使用v-for时添加key属性
splice():函数的使用:删除元素:splice(开始位置,删除元素的个数)
添加元素:splice(开始位置,0, 要添加的元素(如果要添加多个,以逗号分割)),splice(1),从第一个删到最后一个元素,即只留下第一个元素
替换元素:splic(开始位置,要替换元素的个数,要替换的元素(如果有多个,以逗号分割)):也可以理解为,先删除要替换元素的个数的元素,在插入要替换的元素
如果不加key,vue会从第二个位置开始替换,即把第二个位置改为F,第三个位置改为C,…,最后一个位置改为G,性能很低。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in letters" :kye="item">{{item}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G']
}
})
script>
body>
html>
使用key时,vue会把key和要展示的元素一一对应,只要key对应的值不变,他就会不动,key不同的就会在创建一个key和值对应,然后再插入到正确的位置即可。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in letters" :key="item">{{item}}li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['a', 'c', 'd', 'e', 'f']
}
})
script>
body>
html>
push是响应式的:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in letters">{{item}}li>
ul>
<button @click="btnClick">按钮button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['a', 'c', 'd', 'e', 'f']
},
methods: {
btnClick(){
// 1.push方法
// this.letters.push('g');
//2.通过索引值修改数组中的元素
this.letters[0] = 'aaa';
}
}
})
script>
body>
html>
通过索引值修改数组中的元素不能做到响应式点击并不会被修改
一下都是可以做到响应式的方法:
注意:通过索引值修改元素的值不是响应式的。
如果确实要修改,并且要把修改的结果渲染到界面,使用splice函数
也可以使用:Vue.set()函数,该函数时vue内部实现的一个函数
Vue.set(要修改的数组,修改的位置,要修改为什么值)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
.active{
color: red;
}
style>
head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in movies"
:class="{active: currentIndex === index}" @click="liClick(index)">
{{index}}.{{item}}
li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
movies: ['海王', '海贼王', '加勒比海盗', '海尔兄弟', '大海', '小海'],
// 记录当前哪一个li标签显示红色
currentIndex: 0
},
methods: {
liClick(index){
this.currentIndex = index;
}
}
})
script>
body>
html>
项目架构
style.css
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th, td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: center;
}
th {
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
main.js
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《Unix编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '20027-3',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2010-6',
price: 128.00,
count: 1
}
]
}
})
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="style.css">
head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>th>
<th>书籍名称th>
<th>出版日期th>
<th>价格th>
<th>购买数量th>
<th>操作th>
tr>
thead>
<tbody>
<tr v-for="item in books">
<td v-for="value in item">{{value}}td>
tr>
tbody>
table>
div>
<script src="../js/vue.js">script>
<script src="main.js">script>
script>
body>
html>
上面的代码对购买数量中的操作不好做,于是改为下面的方式:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="style.css">
head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>th>
<th>书籍名称th>
<th>出版日期th>
<th>价格th>
<th>购买数量th>
<th>操作th>
tr>
thead>
<tbody>
<tr v-for="item in books">
<td>{{item.id}}td>
<td>{{item.name}}td>
<td>{{item.date}}td>
<td>{{item.price}}td>
<td>
<button>-button>
{{item.count}}
<button>+button>
td>
<td><button>移除button>td>
tr>
tbody>
table>
div>
<script src="../js/vue.js">script>
<script src="main.js">script>
script>
body>
html>
细节处理:如价格保留两位小数和一个¥符号:方式一:toFixed()方法
<td>{{'¥' + item.price.toFixed(2)}}td>
方式二:methods方法
methods: {
getFinalPrice(price){
return '¥' + price.toFixed(2)
}
}
使用:
<td>{{getFinalPrice(item.price)}}td>
方式三:过滤器
filters: {
// 过滤器是一个函数
showPrice(price){
return '¥' + price.toFixed(2)
}
}
使用:{{item.price | 过滤器}}
{{item.price | showPrice}}
添加和删除:
总价格:计算属性
最终:style.css没有变化
main.js
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《Unix编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '20027-3',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2010-6',
price: 128.00,
count: 1
}
]
},
methods: {
/*getFinalPrice(price){
return '¥' + price.toFixed(2)
}*/
increment(index){
this.books[index].count++
},
// 移除
decrement(index){
this.books[index].count--
},
removeHandle(index){
this.books.splice(index, 1)
}
},
filters: {
// 过滤器是一个函数
showPrice(price){
return '¥' + price.toFixed(2)
}
},
computed: {
totalPrice(){
let totalPrice = 0
for(let i = 0; i < this.books.length; i++){
totalPrice += this.books[i].price * this.books[i].count;
}
return totalPrice
}
}
})
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="style.css">
head>
<body>
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th>th>
<th>书籍名称th>
<th>出版日期th>
<th>价格th>
<th>购买数量th>
<th>操作th>
tr>
thead>
<tbody>
<tr v-for="(item, index) in books">
<td>{{item.id}}td>
<td>{{item.name}}td>
<td>{{item.date}}td>
<td>{{item.price | showPrice}}td>
<td>
<button @click="decrement(index)" :disabled="item.count<=1">-button>
{{item.count}}
<button @click="increment(index)">+button>
td>
<td><button @click="removeHandle(index)">移除button>td>
tr>
tbody>
table>
<h3>总价格:{{totalPrice | showPrice}}h3>
div>
<h3 v-else>购物车为空......h3>
div>
<script src="../js/vue.js">script>
<script src="main.js">script>
script>
body>
html>
计算总价格也可以写为:
totalPrice(){
let totalPrice = 0
for(let book of this.books){
totalPrice += book.price * book.count
}
return totalPrice
}
数组操作的高级函数:
以前的编程范式:
另一种分类方式:
例如:
const nums = [10, 20, 111, 222, 444, 40, 50]
// 需求1:取出所有小于100的数字
// 以前的方式
let newNums = []
for(let n of nums){
if(n < 100){
newNums.push(n)
}
}
// 需求2:将所有小于100的数组*2
let new2Nums = []
for(let n of newNums){
new2Nums.push(n * 2)
}
// 需求3:将所有的数字相加得到最终结果
let total = 0
for(let n of new2Nusm){
total += n
}
以上的需求使用高级函数编程:filter(),他需要传一个回调函数(即传一个函数),该回调函数的执行节点:它会在每一次从数组中遍历出来一个数字的时候,就去执行我们传入的函数,并且把遍历出来的数字传给我们的函数,filter中的回调函数有一个要求:必须返回一个Boolean值,当返回true时,函数内部会自动将这次回调传入的值加入到新的数组中,当返回false时,函数内部会过滤掉这次传入的值
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n){
return n < 100
})
高级函数map()的使用:
map()也需要传入一个回调函数,map()传入的函数的返回值作为另一个数组的新的值加入到新的数组中
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n){
return n < 100
})
let new2Nums = newNums.map(function(n){
return n * 2
})
高级函数reduce()的使用:需要出入一个回调函数,回调函数中需要传两个值,一个是前一个值(previousVlaue)和当前遍历的值,这里的previousValue是上一次遍历的值
reduce还有一个重载函数,该重载函数第一个为回调函数,第二个为初始化值
作用:对数组中所有的内容进行汇总
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n){
return n < 100
})
let new2Nums = newNums.map(function(n){
return n * 2
})
// 对new2Nums求和
// 上一次输出的结果:即new2Nums = [20, 40, 80, 100]
// 使用reduce()函数,使用第二个重载函数
// 第一次: preValue 0(自定义初始化值为0),n 20
// 第二次: preValue 20 n 40
// 第三次: preValue 60 n 80
// 第四次: preValue 140 n 100
let total = new2Nums.reduce(function(preValue, n){
return preValue + n
}, 0)
// 最终:total = 240
以上的需求使用更简洁的代码:
const nums = [10, 20, 111, 222, 444, 40, 50]
let total = nums.filter(function(n){
return n < 100
}).map(function(n){
return n * 2
}).reduce(function(preValue, n){
return preValue + n
},0)
还可以使用更简洁的写法:lambda表达式
const nums = [10, 20, 111, 222, 444, 40, 50]
let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)
上面的计算总价的计算属性可以写为:
computed: {
totalPrice(){
return this.books.reduce(function(preValue, book){
return preValue + book.price * book.count
}, 0)
}
}
v-model:表单绑定,表单双向绑定
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" v-model="message">
{{message}}
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
现在vue data中的数据和表单中的数据就进行了双向绑定,即message中的数据会自动填充到表单中,并且只要data或是输入框中的数据发生了变化,另外一方的数据也会同步(及双向绑定)。
以前的mastche是响应式的,即只有vue中的数据变了,才会显示到前端,而前端的数据变了并不会影响到后端。
双向绑定的原理:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" :value="message">
<input type="text" :value="message" @:input="valueChange">
{{message}}
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
valueChange(event){
this.message = event.target.value
}
}
})
script>
body>
html>
简化写法:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" :value="message">
<input type="text" :value="message" @:input="message = $event.target.vlaue">
{{message}}
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
valueChange(event){
this.message = event.target.value
}
}
})
script>
body>
html>
当存在多个单选框时:可以使用v-model直接绑定一个radio中的值到vue的data中
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<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>
<h3>你选择的性别是:{{sex}}h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
// 给定一个默认值
sex: '女'
}
})
script>
body>
html>
效果:
v-model实现单个多选框:一般是跟一个Boolean值绑定
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意协议
label>
<h4>你选择的是:{{isAgree}}h4>
<button :disabled="!isAgree">下一步button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
isAgree: false
}
})
script>
body>
html>
v-model绑定到一个Boolean值是,当点击时该布尔值会执行取反操作
当多选框有多个时:一般是跟一个数组绑定,当用户选择了某个多选框时,v-model绑定的数组就会把该多选框对应的value的值加入到数组中,取消选中时,v-model又会自动移除该值
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="台球" v-model="hobbies">台球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<input type="checkbox" value="足球" v-model="hobbies">足球
<h4>你的爱好是:{{hobbies}}h4>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
hobbies: []
}
})
script>
body>
html>
select(下拉框):也分为选择一个多个的情况
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<select name="test" id="" v-model="fruit">
<option value="苹果">苹果option>
<option value="香蕉">香蕉option>
<option value="桃">桃option>
<option value="西瓜">西瓜option>
<option value="李子">李子option>
select>
<h4>你选择的水果是:{{fruit}}h4>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
// 设置默选中
fruit: '李子'
}
})
script>
body>
html>
选择单个:
选择多个:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<select name="test" id="" v-model="fruit">
<option value="苹果">苹果option>
<option value="香蕉">香蕉option>
<option value="桃">桃option>
<option value="西瓜">西瓜option>
<option value="李子">李子option>
select>
<h4>你选择的水果是:{{fruit}}h4>
<select name="test2" id="t2" v-model="fruits" multiple>
<option value="苹果">苹果option>
<option value="香蕉">香蕉option>
<option value="桃">桃option>
<option value="西瓜">西瓜option>
<option value="李子">李子option>
select>
<h4>你选择的水果是:{{fruits}}h4>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
// 设置默选中
fruit: '李子',
fruits: []
}
})
script>
body>
html>
可以按住ctl键选择多个
我们之前input中的值都是通过value属性绑定的,我们也可以将input中的值在vue的data中预先写好,然后再从vue中取出到前端显示
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<label :for="item" v-for="(item, index) in originHobbies">
<input type="checkbox" :value="item" v-model="hobbies" :id="item">{{item}}
label>
<h4>你的选择是:{{hobbies}}h4>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
originHobbies: ['篮球', '足球', '排球', '乒乓球', '高尔夫球', '台球'],
hobbies: []
}
})
script>
body>
html>
1、lazy修饰符
lazy:懒加载
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" v-model.lazy="message">{{message}}
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
number修饰符:
input输入的东西都会被认为是字符类型,所以使用numer把数字字符转换为数字类型
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" v-model.lazy="message">{{message}}
<br>
<input type="number" v-model.number="age">
<h4>{{age}}--{{typeof(age)}}h4>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
age: 0
}
})
script>
body>
html>
trim修饰符:去除字符串两端空格
虽然浏览器显示时会帮我们自动去除空格,但后端存储的字符串中左右两端的空格还是存在的。
使用trim后
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<input type="text" v-model.lazy="message">{{message}}
<br>
<input type="number" v-model.number="age">
<h4>{{age}}--{{typeof(age)}}h4>
<br>
<input type="text" v-model.trim="content">
<h3>输入为:{{content}}h3>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
age: 0,
content: ''
}
})
script>
body>
html>
空格已被去除
注册组件的基本步骤:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h3>我是标题h3>
<p>我是内容,哈哈哈哈哈哈哈哈哈哈哈哈p>
<p>我是内容,呵呵呵呵呵呵呵呵呵呵呵p>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
上面的内容如果要显示多次,就可以把它抽象为一个组件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<my-cpn>my-cpn>
<my-cpn>my-cpn>
<my-cpn>my-cpn>
<my-cpn>my-cpn>
div>
<script src="../js/vue.js">script>
<script>
// 1.创建组件构造器对象
const cpnC = Vue.extend({
// ES6的新语法: ``包含的字符串可以换行
template: `
我是标题
我是内容,哈哈哈哈哈哈哈哈哈哈哈哈
我是内容,呵呵呵呵呵呵呵呵呵呵呵
`
})
// 2.注册组件:Vue.component('组件的标签名', 组件的构造器对象)
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
以下方式注册的组件为全局组件:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<my-cpn>my-cpn>
div>
<script src="../js/vue.js">script>
<script>
const cpnC = Vue.extend({
template: `
我是标题
我是内容,哈哈哈
`
})
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
全局组件:意味着可以同时再多个vue实列下使用,如下,再创建一个vue实列挂载app2:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<my-cpn>my-cpn>
div>
<div id="app2">
<my-cpn>my-cpn>
div>
<script src="../js/vue.js">script>
<script>
const cpnC = Vue.extend({
template: `
我是标题
我是内容,哈哈哈
`
})
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
const app2 = new Vue({
el: '#app2'
})
script>
body>
html>
怎么注册的组件才是局部组件:在特定的vue下注册的组件是局部组件:
在Vue实列中使用components注册组件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<div id="app2">
<cpn>cpn>
div>
<script src="../js/vue.js">script>
<script>
const cpnC = Vue.extend({
template: `
我是标题
我是内容,哈哈哈
`
})
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: cpnC
}
})
const app2 = new Vue({
el: '#app2'
})
script>
body>
html>
可以发现:cpn在app2的vue实列中不能使用了
注册组件的方式:
这里使用第三种方式
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn2>cpn2>
div>
<script src="../js/vue.js">script>
<script>
// 1.创建第一个组件(子组件)
const cpnC1 = Vue.extend({
template: `
我是标题
我是内容,哈哈哈
`
})
// 2.创建第二个组件构建器(父组件)
const cpnC2 = Vue.extend({
template: `
我是标题
我是内容,呵呵呵
`,
// 在组件构造器2中注册组件构造器1
components: {
cpn1: cpnC1
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
// 这里的组件构造器2中注册了组件构造器1,然后组件构造器2在这里注册,就能保证两个组件构造器都被注册了
components: {
cpn2: cpnC2
}
})
script>
body>
html>
一般认为vue实列也是一个组件
注意:在vue挂载的html下,直接使用在组件构造器中注册的组件是不能被识别的:如下就会报错:
<div id="app">
<cpn2>cpn2>
<cpn1>cpn1>
div>
如果要是用的话,可以在vue的实列中再注册一次:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn2>cpn2>
<cpn1>cpn1>
div>
<script src="../js/vue.js">script>
<script>
// 1.创建第一个组件(子组件)
const cpnC1 = Vue.extend({
template: `
我是标题
我是内容,哈哈哈
`
})
// 2.创建第二个组件构建器(父组件)
const cpnC2 = Vue.extend({
template: `
我是标题
我是内容,呵呵呵
`,
// 在组件构造器2中注册组件构造器1
components: {
cpn1: cpnC1
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
// 这里的组件构造器2中注册了组件构造器1,然后组件构造器2在这里注册,就能保证两个组件构造器都被注册了
components: {
cpn2: cpnC2,
cpn1: cpnC1
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn1>cpn1>
<cpn2>cpn2>
div>
<script src="../js/vue.js">script>
<script>
/*语法糖方式注册:注意内部还是调用extend函数
语法糖注册全局组件*/
Vue.component('cpn1',{
template: `
我是标题
我是内容
`
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
// 语法糖注册局部组件
components: {
'cpn2': {
template: `
我是标题
我是内容
`
}
}
})
script>
body>
html>
也可以写为:key可以加单引号也可以不加
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn1>cpn1>
<cpn2>cpn2>
div>
<script src="../js/vue.js">script>
<script>
/*语法糖方式注册:注意内部还是调用extend函数
语法糖注册全局组件*/
Vue.component('cpn1',{
template: `
我是标题
我是内容
`
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
// 语法糖注册局部组件
components: {
cpn2: {
template: `
我是标题
我是内容
`
}
}
})
script>
body>
html>
语法糖优点:省去了调用extend的步骤
组件模板的简单分离写法:
1、分离写法一
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<script type="text/x-template" id="cpn">
<div>
<h3>我是标题</h3>
<p>我是内容</p>
</div>
script>
<script src="../js/vue.js">script>
<script>
// 使用分离写法注册全局组件,通过script的id获得template内容
Vue.component('cpn', {
template: '#cpn'
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
分离写法2:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<template id="cpn">
<div>
<h3>我是标题h3>
<p>我是内容p>
div>
template>
<script src="../js/vue.js">script>
<script>
Vue.component('cpn', {
template: '#cpn'
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
组件可以访问vue中的数据码?
组件内部是不能直接访问vue实列中的数据的。
结论:组件中也有自己的data属性,但data不能是一个对象,只能以一个函数。而且这个函数返回一个对象,对象内部保存着数据。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<template id="cpn">
<div>
<h3>{{title}}h3>
<p>我是内容p>
div>
template>
<script src="../js/vue.js">script>
<script>
Vue.component('cpn', {
template: '#cpn',
data(){
return{
title: '我是标题'
}
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
vue组件中的data为什么必须是一个组件:
需求:把之前的计数器案例封装为一个组件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<cpn>cpn>
<cpn>cpn>
div>
<template id="cpn">
<div>
<h3>当前计数:{{counter}}h3>
<button @click="increment">+button>
<button @click="decrement">-button>
div>
template>
<script src="../js/vue.js">script>
<script>
// 注册组件
Vue.component('cpn', {
template: '#cpn',
data(){
return{
counter: 0
}
},
methods: {
increment(){
this.counter++
},
decrement(){
this.counter--
}
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
script>
body>
html>
各个组件的counter并不会相互影响:这也是组件中的data必须返回一个函数的原因,因为每个函数都是返回一个对象,每个对象在内存空间中的地址是互不相同的。
下面的代码中,把vue实列看作父组件,组件看作子组件
props:使用数组传递数据:[]数组中单引号中的字符就是在使用该组件时的属性,通过v-bind绑定这个属性就可以把这个值绑定到vue实列中的变量
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn v-bind:cmovies="movies" :cmessage="message">cpn>
div>
<template id="cpn">
<div>
<p>{{cmovies}}p>
<p>{{cmessage}}p>
div>
template>
<script src="../js/vue.js">script>
<script>
// 定义模板对象:在vue中注册实列:
// components{
// cpn: {对象}
// }
//下面定义的对象就是vue实列中要注册的对象
const cpn = {
template: '#cpn',
// 可以使用数组形式传递数据
props: ['cmovies', 'cmessage']
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
movies: ['海王', '海贼王', '海尔兄弟']
},
// 注册组件:使用属性增强写法
components: {
cpn
}
})
script>
body>
html>
注意:在使用组件时必须使用v-bind,如果不使用的话,vue会直接把双引号中的字符穿个组件props数组中的变量。
错误使用如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn cmovies="movies" cmessage="message">cpn>
div>
<template id="cpn">
<div>
<p>{{cmovies}}p>
<p>{{cmessage}}p>
div>
template>
<script src="../js/vue.js">script>
<script>
// 定义模板对象:在vue中注册实列:
// components{
// cpn: {对象}
// }
//下面定义的对象就是vue实列中要注册的对象
const cpn = {
template: '#cpn',
// 可以使用数组形式传递数据
props: ['cmovies', 'cmessage']
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
movies: ['海王', '海贼王', '海尔兄弟']
},
// 注册组件:使用属性增强写法
components: {
cpn
}
})
script>
body>
html>
使用数组的话:[]中放的是字符,而我们又把它当作变量使用,不符合习惯。
传递方式二:props中使用对象(好处:可以指定类型)
props: {
//类型限制
cmovies: Array,
cmessage: String
}
还可以提供默认值:默认值在父组件没有传递值的时候显示
props: {
cmovies: Array,
cmessage: {
type: String,
default: 'hello',
// required为true时要求使用的时候必须传值
required: true
}
}
类型是数组或对象时默认值需要使用工厂函数返回
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :cmessage="message">cpn>
div>
<template id="cpn">
<div>
<p>{{cmovies}}p>
<p>{{cmessage}}p>
div>
template>
<script src="../js/vue.js">script>
<script>
// 定义模板对象:在vue中注册实列:
// components{
// cpn: {对象}
// }
//下面定义的对象就是vue实列中要注册的对象
const cpn = {
template: '#cpn',
// 可以使用数组形式传递数据
props: {
cmovies: {
type: Array,
default(){
return []
}
},
cmessage: {
type: String,
default: 'hello',
required: true
}
}
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
movies: ['海王', '海贼王', '海尔兄弟']
},
// 注册组件:使用属性增强写法
components: {
cpn
}
})
script>
body>
html>
其他写法:
注意:目前的vue中v-bind不支持驼峰命名,因此在有v-bind的地方,驼峰命名需要转换为-连接的形式
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :cinfo="info">cpn>
div>
<template id="cpn">
<div>{{cinfo}}div>
template>
<script src="../js/vue.js">script>
<script>
const cpn = {
template: '#cpn',
props: {
cinfo: {
type: Object,
default(){
return {}
}
}
}
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
info: {
name: 'why',
age: 18,
height: 188
}
},
components: {
cpn
}
})
script>
body>
html>
有驼峰命名时:
转化例子:myChildrenMessage 转换为 my-children-message
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :c-info="info">cpn>
div>
<template id="cpn">
<div>{{cInfo}}div>
template>
<script src="../js/vue.js">script>
<script>
const cpn = {
template: '#cpn',
props: {
cInfo: {
type: Object,
default(){
return {}
}
}
}
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
info: {
name: 'why',
age: 18,
height: 188
}
},
components: {
cpn
}
})
script>
body>
html>
父子间的通信:子传父
子组件通过$emit(‘要发送的事件名’,传递的参数)发送事件,父组件通过使用子组件时,监听子组件发送的事件获取子组件发来的数据:(注意子组件中不要使用驼峰命名),在脚手架中可以使用驼峰命名
父组件监听语法:@子组件发送的事件名=“父组件中的处理函数”
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn @item-click="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: '手机数码'}
]
}
},
methods: {
btnClick(item){
// 把我们点击了谁传递给父组件:$emit('要发送的事件名',传递的参数)
this.$emit('item-click', item)
console.log(item);
}
}
}
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn
},
methods: {
cpnClick(item){
console.log("父组件", item);
console.log("conClick")
}
}
})
script>
body>
html>
计算属性
事件监听
修饰符
条件判断
循环遍历
数组遍历
对象遍历
数组的那些方法是响应式的
作业完成
书籍案例
v-model的基本使用
v-model的修饰符
组件化开发
组件数据的存放
父子组件的通信
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :number1="num1" :number2="num2">cpn>
div>
<template id="cpn">
<div>
<h4>props:{{number1}}h4>
<input type="text" v-model="number1">
<h4>props:{{number2}}h4>
<input type="text" v-model="number2">
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
num1: 1,
num2: 0
},
components: {
cpn: {
template: '#cpn',
props: {
number1: Number,
number2: Number
}
}
}
})
script>
body>
html>
子组件中的props和input直接进行双向绑定,这是官方不推荐使用的方式,因为props中的数据是父组件传来的,它的值应该有父组件去改变,如果直接通过v-model直接修改,将会导致修改混乱,因此报错(虽然可以修改),官方推荐我们使用计算属性或者data去修改props中的值
正确的修改方法
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :number1="num1" :number2="num2">cpn>
div>
<template id="cpn">
<div>
<h4>props:{{number1}} data:{{dnumber1}}h4>
<input type="text" v-model="dnumber1">
<h4>props:{{number2}} data:{{dnumber2}}h4>
<input type="text" v-model="dnumber2">
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
num1: 1,
num2: 0
},
components: {
cpn: {
template: '#cpn',
props: {
number1: Number,
number2: Number
},
data(){
return{
dnumber1: this.number1,
dnumber2: this.number2
}
}
}
}
})
script>
body>
html>
现在的需求:希望子组件中的输入框中的值改变的时候,父组件中的num1和num2也随着改变
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :number1="num1" :number2="num2"
@num1change="num1Change"
@num2change="num2Change">cpn>
div>
<template id="cpn">
<div>
<h4>props:{{number1}} data:{{dnumber1}}h4>
<input type="text" :value="dnumber1" @input="num1Input">
<h4>props:{{number2}} data:{{dnumber2}}h4>
<input type="text" :value="dnumber2" @input="num2Input" >
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
num1: 1,
num2: 0
},
methods:{
num1Change(value){
// 因为value是子组件输入框传来的数据,默认是字符串,所以因该把它转换为int型
// 转换方法一:使用*数字的方法: 如 this.num1 = value * 1
// 方式二:使用parseInt方法
this.num1 = parseInt(value)
},
num2Change(value){
this.num2 = parseInt(value)
}
},
components: {
cpn: {
template: '#cpn',
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)
}
}
}
}
})
script>
body>
html>
新的需求:让上面的data是下面data的1/100,下面data是上面data的100倍
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn :number1="num1" :number2="num2"
@num1change="num1Change"
@num2change="num2Change">cpn>
div>
<template id="cpn">
<div>
<h4>props:{{number1}} data:{{dnumber1}}h4>
<input type="text" :value="dnumber1" @input="num1Input">
<h4>props:{{number2}} data:{{dnumber2}}h4>
<input type="text" :value="dnumber2" @input="num2Input" >
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
num1: 1,
num2: 0
},
methods:{
num1Change(value){
// 因为value是子组件输入框传来的数据,默认是字符串,所以因该把它转换为int型
// 转换方法一:使用*数字的方法: 如 this.num1 = value * 1
// 方式二:使用parseInt方法
this.num1 = parseFloat(value)
},
num2Change(value){
this.num2 = parseFloat(value)
}
},
components: {
cpn: {
template: '#cpn',
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)
// 同时修改dnumber2的值
this.dnumber2 = this.dnumber1 * 100
// 同时让如组件的num2也改变
this.$emit('num2change', this.dnumber2)
},
num2Input(event){
this.dnumber2 = event.target.value
this.$emit('num2change', this.dnumber2)
this.dnumber1 = this.dnumber2 / 100
// 同时让如组件的num2也改变
this.$emit('num1change', this.dnumber1)
}
}
}
}
})
script>
body>
html>
案例逻辑整理:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<button @click="btnClick">点击button>
div>
<template id="cpn">
<div>我是子组件div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
btnClick(){
// 通过$children访问子组件
console.log(this.$children);
}
},
components: {
cpn: {
template: '#cpn',
methods: {
showMessage(){
console.log("showMessage");
}
}
}
}
})
script>
body>
html>
可以发现this.$children拿到的是一个数组,并且这个数组中有一个VueComponent的vue组件,该组件可以看到我们定义的方法
于是我们通过该数组中的vue组件拿到刚才我们定义个函数
this.$children[0].showMessage()
拷贝三个组件:
<div id="app">
<cpn>cpn>
<cpn>cpn>
<cpn>cpn>
<button @click="btnClick">点击button>
div>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<cpn>cpn>
<cpn>cpn>
<button @click="btnClick">点击button>
div>
<template id="cpn">
<div>我是子组件div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
btnClick(){
// 通过$children访问子组件
console.log(this.$children);
// 拿到子组件中的方法
this.$children[0].showMessage()
// 去除name的name
for(let c of this.$children){
console.log(c.name);
c.showMessage()
}
}
},
components: {
cpn: {
template: '#cpn',
data(){
return{
name: '我是子组件的name'
}
},
methods: {
showMessage(){
console.log("showMessage");
}
}
}
}
})
script>
body>
html>
如果我们要拿到子组件中内容,一般不会使用 c h i l d r e n ( 如 果 以 后 的 代 码 修 改 了 , 通 过 下 标 闹 到 的 内 容 就 会 改 变 ) , 而 是 使 用 另 一 个 方 法 : children(如果以后的代码修改了,通过下标闹到的内容就会改变),而是使用另一个方法: children(如果以后的代码修改了,通过下标闹到的内容就会改变),而是使用另一个方法:refs
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn ref="a">cpn>
<cpn ref="b">cpn>
<cpn ref="c">cpn>
<button @click="btnClick">点击button>
div>
<template id="cpn">
<div>我是子组件div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
methods: {
btnClick(){
// 通过$children访问子组件
console.log(this.$children);
// 拿到子组件中的方法
this.$children[0].showMessage()
// 去除name的name
for(let c of this.$children){
console.log(c.name);
c.showMessage()
}
// 通过ref拿到子组件对象
console.log(this.$refs.a)
// 拿到name属性
console.log(this.$refs.a.name)
}
},
components: {
cpn: {
template: '#cpn',
data(){
return{
name: '我是子组件的name'
}
},
methods: {
showMessage(){
console.log("showMessage");
}
}
}
}
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<template id="cpn">
<div>
<h4>我是子组件h4>
<button @click="btnClick">按钮button>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn',
methods: {
// 1.访问父组件:$parent
btnClick(){
console.log(this.$parent);
}
}
}
}
})
script>
body>
html>
打印出来是一个Vue,这是因为该子组件的父亲就是vue实列
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<template id="cpn">
<div>我是cpn组件
<ccpn>ccpn>
div>
template>
<template id="ccpn">
<div>
<h4>我是子组件h4>
<button @click="btnClick">按钮button>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn',
data(){
return{
name: '我是cpn组件的name'
}
},
// 在嵌套一个子组件
components: {
ccpn: {
template: '#ccpn',
methods: {
// 1.访问父组件:$parent
btnClick(){
console.log(this.$parent);
// 拿到父组件的name
console.log(this.$parent.name);
// 访问根组件
console.log(this.$root);
// 访问根组件的message
console.log(this.$root.message);
}
}
}
}
}
}
})
script>
body>
html>
插槽:slot
需求不一样:
希望插槽具有扩展性
使用插槽:抽取共性,保留不同
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn><button>按钮button>cpn>
<cpn><span>哈哈哈span>cpn>
<cpn><i>呵呵呵i>cpn>
<cpn><button>按钮button>cpn>
div>
<template id="cpn">
<div>
<h4>我是组件h4>
<p>哈哈哈p>
<slot>slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
也可以给插槽一个默认值:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<cpn><span>哈哈哈span>cpn>
<cpn><i>呵呵呵i>cpn>
<cpn>cpn>
div>
<template id="cpn">
<div>
<h4>我是组件h4>
<p>哈哈哈p>
<slot><button>按钮button>slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
如果一个插槽中插入多个值,则插槽会把所有的内容都插进去
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>
<i>呵呵呵i>
<span>哈哈哈span>
<button>按钮button>
cpn>
div>
<template id="cpn">
<div>
<h4>我是组件h4>
<p>哈哈哈p>
<slot><button>按钮button>slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
指定位置插入:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn><span>标题span>cpn>
div>
<template id="cpn">
<div>
<slot><span>左边span>slot>
<slot><span>中间span>slot>
<slot><span>右边span>slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
这时vue会把所有的都替换掉,要解决这个问题,需要指定名字(具名)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn><span>标题span>cpn>
div>
<template id="cpn">
<div>
<slot name="left"><span>左边span>slot>
<slot name="mid"><span>中间span>slot>
<slot name="right"><span>右边span>slot>
<slot>哈哈slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
这时只会替换没有名字的:
具名插槽的使用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn><span slot="mid">标题span>cpn>
<cpn><button slot="left">返回button>cpn>
div>
<template id="cpn">
<div>
<slot name="left"><span>左边span>slot>
<slot name="mid"><span>中间span>slot>
<slot name="right"><span>右边span>slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn'
}
}
})
script>
body>
html>
组件和vue实列中各有一个isShow,其中实列中的isShow为true, 组件中的为false,我们在使用组件时,使用isShow,他用的是哪里的isShow?
使用的是vue实例中的isShow
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn v-show="isShow">cpn>
div>
<template id="cpn">
<div>
<h4>我是子组件h4>
<p>哈哈哈p>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
isShow: true
},
components: {
cpn: {
template: '#cpn',
data(){
return{
isShow: false
}
}
}
}
})
script>
body>
html>
修改为false时:
通过实验发现,绑定的变量它只看他在那个模板下,刚才我们使用cpn组件是在vue实例下,所以他使用的是vue实例下的遍变量,它不管使用的是那个组件
父组件替换插槽的标签,但是内容有子组件提供
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
div>
<template id="cpn">
<div>
<ul>
<li v-for="item in pLanguages">{{item}}li>
ul>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn',
data(){
return {
pLanguages: ['javaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift']
}
}
}
}
})
script>
body>
html>
默认展示效果
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<cpn>
<template slot-scope="slot">
<span v-for="item in slot.data">{{item}} - span>
template>
cpn>
<cpn>
<template slot-scope="slot">
<span v-for="item in slot.data">{{item}} * span>
template>
cpn>
div>
<template id="cpn">
<div>
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}li>
ul>
slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn',
data(){
return {
pLanguages: ['javaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift']
}
}
}
}
})
script>
body>
html>
去除尾部的-或*:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<cpn>cpn>
<cpn>
<template slot-scope="slot">
<span>{{slot.data.join(' * ')}}span>
template>
cpn>
<cpn>
<template slot-scope="slot">
<span>{{slot.data.join(' - ')}}span>
template>
cpn>
div>
<template id="cpn">
<div>
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}li>
ul>
slot>
div>
template>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
cpn: {
template: '#cpn',
data(){
return {
pLanguages: ['javaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift']
}
}
}
}
})
script>
body>
html>
作用插槽:就是让父组件拿到子组件中的数据,并以自己希望的格式展示。
javascript
别人改了自己的变量,导致的问题:
示例项目结构
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="main.js">script>
<script src="a.js">script>
<script src="b.js">script>
<script src="xm.js">script>
<script>script>
body>
html>
main.js:没有写内容
a.js
// 小明
var name = '小明'
var age = 20
function sum(num1, num2){
return num1 + num2
}
var flag = true
if(flag){
console.log(sum(12, 20))
}
b.js
// 小红
var name = '小红'
var flag = false
console.log(name)
xm.js
if(flag){
console.log("小明是天才");
}
运行时发现:小明是天才没有输出,因为小明知道自己定义了一个flag变量,并且为true
之前问题的解决方式之一:
使用匿名函数闭包解决
a.js
// 小明
(function(){
var name = '小明'
var age = 20
function sum(num1, num2){
return num1 + num2
}
var flag = true
if(flag){
console.log(sum(12, 20))
}
})()
但这时又带了一个问题,我想在xm.js中使用flag和sum函数时,发现不能用了,即代码的复用性大打折扣。
解决方式二:模块化
index.html:一样
a.js
// 小明
// 导出后:moduleA就等价于obj,而moduleA属于全局变量
var moduleA = (function(){
// 定义导出的对象
var obj = {}
var name = '小明'
var age = 20
function sum(num1, num2){
return num1 + num2
}
var flag = true
if(flag){
console.log(sum(12, 20))
}
// 给obj动态加一个属性flag和一个函数sum
obj.flag = flag;
obj.sum = sum;
// 导出
return obj
})()
b.js
// 小红
var moduleB = (function(){
var obj = {}
var name = '小红'
var flag = false
console.log(name)
obj.flag = flag
return obj
})()
xm.js
if(moduleA.flag){
console.log("小明是天才");
}
结果
这是之前常用的解决命名冲图的办法,现在几乎不这样做了,因为现在有很多别人写好的,规范的模块化开发框架规范,我们直接使用就可以了。
常见的模块化规范:
CommonJS,AMD,CMD,也有ES6的Modules
CommonJS只是一个规范,具体的实现有一个比较著名的:Node
了解CommonJs:以下的语法需要底层Node的支持
导出/导入: export/import
示例项目结构
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="a.js" type="module">script>
<script src="b.js" type="module">script>
<script src="xm.js" type="module">script>
body>
html>
a.js
导出方式一:
var name = '小明'
var age = 18
var flag = true
function sum(num1, num2){
return num1 + num2
}
if(flag){
console.log(sum(10, 20));
}
// 导出flag和sum
// 导出一个对象:export{}
export{
// es6的增强写法
flag,sum
}
b.js
var name = '小红'
var age = 20
var flag = false
xm.js
import {flag, sum} from "./a.js"
if(flag){
console.log("小明是天才");
}
导出方式二:a.js
var name = '小明'
var age = 18
var flag = true
function sum(num1, num2){
return num1 + num2
}
if(flag){
console.log(sum(10, 20));
}
// 导出flag和sum
// 导出一个对象:export{}
// 导出方式一
export{
// es6的增强写法
flag,sum
}
// 导出方式二
export var num1 = 1000
export var height = 188
// 导出函数或类
export function mul(num1, num2){
return num1 * num2
}
// 导出类
export class Person{
run(){
console.log("在奔跑");
}
}
// export default:导入时可以自己命名,在一个js文件中,export default只能有一个
const address = '北京市'
export default address
xm.js
import {flag, sum} from "./a.js"
import {num1, height} from "./a.js";
if(flag){
console.log("小明是天才");
}
console.log(num1, height)
// 导入类和函数
import {mul, Person} from './a.js'
console.log(mul(220, 30));
const p = new Person()
p.run()
// 导入default,可以自定义名字
import addr from './a.js'
console.log(addr);
同一全部导入:
import {flag, sum} from "./a.js"
import {num1, height} from "./a.js";
if(flag){
console.log("小明是天才");
}
console.log(num1, height)
// 导入类和函数
import {mul, Person} from './a.js'
console.log(mul(220, 30));
const p = new Person()
p.run()
// 导入default,可以自定义名字
import addr from './a.js'
console.log(addr);
// 同一全部导入
import * as ex from './a.js'
console.log(ex.sum(12, 13));
上面的代码属于ES6规范,es6规范,浏览器都做了支持。
webpack是一个现代的JavaScript应用静态模块打包工具:模块和打包