赞
踩
1.v-for循环数字,数组,对象
-<标签 v-for='i in 变量'>{{i}}----{{变量}}<标签>
2.事件处理
-input标签的事件: change(input框里面的数据发生变化,光标移开,才会触发),blur(input框只要光标移开,才会触发),input(只要输入一个东西,光标移开,就会触发)
3.数据双向绑定
-input标签 v-model
4.过滤案例
-触发input事件,让新的数组变化
-变量=数组.filter(item=>{})
-字符串.indeOf('子字符串')
5.事件修饰符
-stop:阻止事件冒泡
-self:只执行自己的事件
-prevent:阻止a标签跳转
-once:只执行一次
6.按键修饰符
-@keyUp enter用的最多
7.input标签
-checkbox:作为单选的时候---》js变量 的布尔值
-radio:js变量的字符串
-checkbox 多选:js变量的数组
下面这种写法也是可以的
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<style>
table, td {
border: 1px solid black;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<h1>购物车</h1>
<table>
<tr>
<td>商品名称</td>
<td>价格</td>
<td>数量</td>
<td>选择</td>
</tr>
<tr v-for="item in dataList">
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.number}}</td>
<td><input type="checkbox" v-model="choice" :value="item"></td>
</tr>
</table>
选中的商品是:{{choice}}
<br>
<!-- 插值语法里面,写函数加括号,就会执行这个函数-->
商品价格:{{getPrice()}}
</div>
</body>
<script>
let vm = new Vue({ //ES6之后,都是推荐时间let
el: "#app",
data: {
dataList: [
{name: '今瓶没', price: 99, number: 2},
{name: '西柚记', price: 59, number: 1},
{name: '水壶转', price: 89, number: 5},
],//这个数据是后端返回的
choice: []
},
methods: {
getPrice() {
// 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
let totle = 0
// for (let i = 0; i < this.choice.length; i++) {
// totle = totle + this.choice[i].price * this.choice[i].number;
// }
// return totle
// 还有别的写法
// for (i in this.choice) { // 这里的i是索引
// totle += this.choice[i]['number'] * this.choice[i]['price'] // ['price'],用点也可以
// }
// return totle
// 还有别的写法:es6的循环方式
// for (v of this.choice) { // 这里的v是数组中的每一个对象
// totle += v.price * v.number
// }
// return totle
// 还有别的写法:对象的迭代方法(了解)
this.choice.forEach(function (value, index) { // 匿名函数,亦可以用箭头 this.choice.forEach((value, index)=>{
totle += value.price * value.number
})
return totle
}
}
})
</script>
</html>
下面再实现一个:购物车案例加上全选,全不选的按钮
还有一个问题是,当我把所有的枚举值都选中的时候,上面的全选也应该勾选
所以得加上一个逻辑:就是下面的枚举值,被选上的时候,要检查一下上面的全选勾的状态
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<style>
table, td {
border: 1px solid black;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<h1>购物车</h1>
<table>
<tr>
<td>商品名称</td>
<td>价格</td>
<td>数量</td>
<td>选择 <input type="checkbox" v-model="checkAll" @change="handleAll"></td>
</tr>
<tr v-for="item in dataList">
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.number}}</td>
<td><input type="checkbox" v-model="choice" :value="item" @change="checkOne"></td>
</tr>
</table>
选中的商品是:{{choice}}
<br>
<!-- 插值语法里面,写函数加括号,就会执行这个函数-->
商品价格:{{getPrice()}}
</div>
</body>
<script>
let vm = new Vue({ //ES6之后,都是推荐时间let
el: "#app",
data: {
dataList: [
{name: '今瓶没', price: 99, number: 2},
{name: '西柚记', price: 59, number: 1},
{name: '水壶转', price: 89, number: 5},
],//这个数据是后端返回的
choice: [],
checkAll: false
},
methods: {
getPrice() {
// 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
let totle = 0
//es6的循环方式
for (v of this.choice) { // 这里的v是数组中的每一个对象
totle += v.price * v.number
}
return totle
},
handleAll() {
if (this.checkAll) {
this.choice = this.dataList //这个是全选的时候
} else {
this.choice = []//这个是全不选的时候
}
},
checkOne() {
//逻辑就是:this.choice = this.dataList的长度,就全选中,全选中的话,就让checkAll变成true
if (this.choice.length == this.dataList.length) {
this.checkAll=true
}else{
this.checkAll=false
}
}
},
})
</script>
</html>
功能车功能完成
实现在数量前面加上+—号,用来调整数量,当数量减到1的时候,就不能减了
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<style>
table, td {
border: 1px solid black;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<h1>购物车</h1>
<table>
<tr>
<td>商品名称</td>
<td>价格</td>
<td>数量</td>
<td>选择 <input type="checkbox" v-model="checkAll" @change="handleAll"></td>
</tr>
<tr v-for="item in dataList">
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<!-- @click="item.number++">:这里也可以写简单的js代码,跟插值一样-->
<!-- 这里可以写item.number++ 写减减@click="item.number--"的话,会出现负数,所以不能这样写-->
<!-- handleJ(item),参数是要减的对象,得传进去-->
<td><button @click="handleJ(item)">-</button>{{item.number}}<button @click="item.number++">+</button></td>
<td><input type="checkbox" v-model="choice" :value="item" @change="checkOne"></td>
</tr>
</table>
选中的商品是:{{choice}}
<br>
<!-- 插值语法里面,写函数加括号,就会执行这个函数-->
商品价格:{{getPrice()}}
</div>
</body>
<script>
let vm = new Vue({ //ES6之后,都是推荐时间let
el: "#app",
data: {
dataList: [
{name: '今瓶没', price: 99, number: 2},
{name: '西柚记', price: 59, number: 1},
{name: '水壶转', price: 89, number: 5},
],//这个数据是后端返回的
choice: [],
checkAll: false
},
methods: {
getPrice() {
// 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
let totle = 0
//es6的循环方式
for (v of this.choice) { // 这里的v是数组中的每一个对象
totle += v.price * v.number
}
return totle
},
handleAll() {
if (this.checkAll) {
this.choice = this.dataList //这个是全选的时候
} else {
this.choice = []//这个是全不选的时候
}
},
checkOne() {
//逻辑就是:this.choice = this.dataList的长度,就全选中,全选中的话,就让checkAll变成true
if (this.choice.length == this.dataList.length) {
this.checkAll=true
}else{
this.checkAll=false
}
},
handleJ(item){
if (item.number<=1){
alert('不能再少了')
}else {
item.number--
}
}
},
})
</script>
</html>
关于备案(插播):
现在我们用django或其他写了一个项目,项目是在服务器上的。服务器可以是自己电脑,这样的话,别人就不能访问到你,因为没有公网IP,所以访问不到你
一般我们公司都是用的一个公网地址
所以需要去买一台带公网的IP,买一台云服务器(阿里云之内的,就是租了一台服务器,把自己的项目部署在上面),还要再买一个公网ip,需要把ip绑定到这个公网ip上面
但是现在的访问,不是基于ip的访问,还要买一个域名,自己去选
别人访问你的域名,域名在转发到公网ip上,是DNS解析
买的这个域名,在国内必须要备案(说明是干嘛要的)
买阿里云的话,阿里云会协助你在工信部备案,大概两个星期。要身份证正反面
V-model进阶
不是特别重要
lazy:等待input框的数据绑定时区焦点之后再变化
指的是input框,本来数据的双向绑定,只要页面一变,数据就跟着变化、
现在是焦点失去之后,js的变量在变,相当于懒加载一下,就不是实时的更新,实时的更新的话,是需要消耗一定的资源的
number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
trim:去除首位的空格
lazy
number
trim
去除前后空格,相当于Python的.strip
Vue生命周期钩子函数
指的是Vue的组件,有8个
create 创建
mount 挂载
update 更新
1.bedoreCreate
2.created
3.beforeMount
4.mounted(用得最多)
5.beforeUpdate
6.updated
7.beforeDestroy 销毁之前
8.destroyed 销毁
就是到那个地方,就会触发他的执行
我们的目的是在某一个地方,重写钩子函数,去实现自己的功能
比如:在create的时候,去后端加载数据,数据回来之后,还没有挂载整个页面,这时数据已经过来了,效率上就比较快
beforeCreate 创建Vue实例之前调用
created 创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
beforeMount 渲染DOM之前调用
mounted 渲染DOM之后调用
beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated 重新渲染完成之后调用
beforeDestroy 销毁之前调用
destroyed 销毁之后调用
记住:有8个东西,用就用created,就行了
挂载完之后,现在就停在这里了,等待组件里面的数据变化,只要有变化,就会触发updated、beforeUpdate
重点:
1、created:在这个里面向后端发送请求,获取数据
2、mounted:
定时器:用处很大,轮训。跟后端交互,比如拿后端数据(一种就是像这样向后端轮训,还有一种就是websocket)
this.t = setInterval(function () {
console.log('daada')
}, 3000) // js代码:每隔3秒钟,干一件事(console.log('daada'))
关掉定时器:
clearInterval(this.t)
延迟任务:
this.t = setTimeout(function () {
console.log('daada')
}, 3000) // js代码:3秒后执行代码console.log('daada')
20
在任何一个Vue对象里面,都可以写这8个生命周期函数,跟写的顺序没有关系,跟钩子的名字有关
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生命周期</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<child v-if="isShow"></child>
<br>
<button @click="terminate">删除子组件</button>
<button @click="reborn">显示子组件</button>
</div>
</body>
<script>
Vue.component('child', {
template: `
<div>
{{name}}
<button @click="name='Darker1'">更新数据1</button>
<button @click="name='Darker2'">更新数据2</button>
</div>`,
data() {
return {
name: 'Darker1',
}
},
beforeCreate() {
console.group('当前状态:beforeCreate')
console.log('当前el状态:', this.$el) // 指的是上面的模板:template里面的div
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
created() {
console.group('当前状态:created')// 可以打印出分组的效果:可以收缩
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeMount() {
console.group('当前状态:beforeMount')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
mounted() {
console.group('当前状态:mounted')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
//用的最多,向后端加载数据,创建定时器等
console.log("页面已被vue实例渲染, data, methods已更新");
console.log('mounted')
this.t = setInterval(function () {
console.log('daada')
}, 3000) // js代码:每隔3秒钟,干一件事(console.log('daada'))
},
beforeUpdate() {
console.group('当前状态:beforeUpdate')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
updated() {
console.group('当前状态:updated')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeDestroy() {
console.group('当前状态:beforeDestroy')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
destroyed() {
console.group('当前状态:destroyed')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
//组件销毁,清理定时器
clearInterval(this.t)
this.t = null //销毁定时器
console.log('destoryed')
},
})
let vm = new Vue({
el: '#box',
data: {
isShow: true
},
methods: {
terminate() {
this.isShow = false
},
reborn() {
this.isShow = true
}
}
})
</script>
</html>
axios跟后端交互
并不是只有jquery能发Ajax,原生的js就可以发ajax请求。问题在于不同的浏览器兼容性不好。jquery处理了这个兼容性的问题
在vue里面不推崇用jquery的ajax发请求了
axios:只有ajax,没有别的。不需要引入jquery
现在通过前端页面,向这个地址发请求,拿数据
会出现跨域问题。
之前没有出现跨域问题,是因为前后端混合开发,发的请求就是服务器的地址
现在是重一个端口向5000端口发请求,这样就被阻止了,这个是浏览器的一个安全策略
处理这个问题,很简单,需要在响应头里面加一个东西
这样前端就能拿到后端的数据了,现在需要把渲染到页面上面
实际项目中,后端的数据,会从数据库之内的地方拿
当然:axios也可以发送post请求
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跟后端交互</title>
<script src="./js/vue.js"></script>
<!-- 引入axios的cdn,也可以下载下来放在本地-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick">点我看美女</button>
<br>
我的名字是:{{name}}
<br>
我的年龄是:{{age}}
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {
name : "",
age : 0
},
methods: {
handleClick(){
// 会出现跨域问题
axios.get("http://127.0.0.1:5000").then(res=>{
console.log(res["data"])
this.name = res.data.name
this.age = res.data.age
}) // 发送get请求;匿名函数,可以用箭头;返回的结果就在这个res里面
}
}
})
</script>
</html>
后端代码:
from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.route("/")
def index():
# return jsonify({"name": "lqz", "age": 19})
obj = make_response(jsonify({"name": "lqz", "age": 19}))
obj.headers["Access-Control-Allow-Origin"] = "*" # 往消息头里面加东西
return obj
if __name__ == '__main__':
app.run()
# 访问根路径,就返回一个{"name": "lqz", "age": 19}的接口
前端显示电影
页面什么时候加载?我们放在生命周期的钩子函数上面,当页面created的时候
后端代码:
from flask import Flask, jsonify, make_response
import json
app = Flask(__name__)
@app.route("/")
def index():
with open("a.json", "r", encoding="utf8") as f:
res = json.load(f)
obj = make_response(jsonify(res))
obj.headers["Access-Control-Allow-Origin"] = "*" # 往消息头里面加东西
return obj
if __name__ == '__main__':
app.run()
# 访问根路径,就返回一个{"name": "lqz", "age": 19}的接口
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跟后端交互</title>
<script src="./js/vue.js"></script>
<!-- 引入axios的cdn,也可以下载下来放在本地-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box">
<ul>
<li v-for="item in datalist">
<p>电影标题:{{item.name}}</p>
<p>电影主演:{{item.director}}</p>
<img :src="item.poster" alt="">
</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {
datalist : []
},
created(){
axios.get("http://127.0.0.1:5000/").then(res =>{
this.datalist= res.data.data.films
})
}
})
</script>
</html>
向后端发送请求,就在created里面写
计算属性
先实现一个需求,一输入内容,就将首字母变成大写
这样实现的话,里面的逻辑太多了,不好。可以写一个方法
上面写在插值里面和写成函数都是OK的
写成函数不好的地方就是,如果再调用一次,就又要执行,这样就不太好,最好写成计算属性
计算属性的意思是把这个东西当做属性来用,里面用多次之后,不会重复计算
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 现在想要实现一输入内容,就将首字母变成大写,后面直接写msg,肯定不行-->
<!-- 希望能有一些js代码来支持:msg.substring(0,1)获取从0到第一个字母,.toUpperCase()转大写,msg.substring(1)是1到最后都截-->
<input type="text" v-model="msg">
<br> 直接在插值中写代码:
{{msg.substring(0, 1).toUpperCase() + msg.substring(1)}}
<br> 写成一个函数:
{{getMsg()}}
<br> 使用计算属性
{{getMsg}}
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {},
methods : {
getMsg(){
return this.msg.substring(0, 1).toUpperCase() + this.msg.substring(1)
}
},
computed : {
getMsg() {
return this.msg.substring(0, 1).toUpperCase() + this.msg.substring(1)
}
}
})
</script>
</html>
组件化开发
全局组件
后面开发的时候,头部、中间、侧部的东西可以直接引过来用。
组件分为全局组件和局部组件
定义一个全局组件
组件名字是child,template(必须是template,可以不加引号)里面写html内容(反引号可以换行)
template里面只能有一个闭合标签,下面写的是div
组件里面的data必须是函数,返回对象
组件有自己的样式,数据,方法
这个就是组件化开发
局部组件
局部组件要么定义在根Vue里面,要么定义在Vue组件里面
类似于上面的这个图,头可以有组件,导航可以有组件,里面的任何都可以做成组件
全局组件的定义,可以用在跟组件上面
局部组件的定义,只能用在内部
组件都有自己的生命周期,包括计算属性
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<child></child>
<hr>
</div>
</body>
<script>
// 定义一个全局组件,在全局组件中定义一个局部组件
Vue.component('child', {
template: `
<div>
<h1>我是子组件</h1>
<br>
<button @click="handleClick">点我看美女--{{ name }}</button>
<hr>
<header1></header1>
</div>
`,
data() {
return {
name: 'lqz'
}
},
methods: {
handleClick() {
alert('美女')
}
},
components: {
'Header1': {
template: `<h2>我是局部组件---{{ msg }}</h2>`,// 组件只能用自己的值,不能用别的组件的数据
data() {
return {
msg: 'SB'
}
},
methods: {},
}
}
})
// 上面定义的子组件Header1,只能用在局部child里面
let vm = new Vue({
el: '#box',
data: {},
})
</script>
</html>
组件通讯之父传子(通过属性)
上面讲了全局组件和局部组件,两者之间的数据是不能共享的,现在就需要实现这个共享
上面的代码里面:child是父,Header1是子;
也可以是:上面的vue div是父,child是子
现在想实现将Vue里面的数据传到child里面,就是父传子
1、在子组件上自定义一个属性,绑定好一个变量 <child :mymsg="msg"></child>,这个变量msg是父组件的变量
2、在子组件里面写一个props,后面接数组,有几个可以写几个:props:['mymsg'],数组里面是属性的名字。写了属性名字之后,就可以当做变量来用了
通过自定义属性实现父传子
再传一个数据过来
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 在组件上自定义属性,使用属性指令,绑定好变量-->
<child :mymsg="msg" :age="age"></child>
<hr>
</div>
</body>
<script>
// 定义一个全局组件,在全局组件中定义一个局部组件
Vue.component('child', {
template: `
<div>
<h1>我是子组件---从父组件传值过来--{{mymsg}}---{{age}}</h1>
<br>
<button @click="handleClick">点我看美女--{{ name }}</button>
<hr>
</div>
`,
data() {
return {
name: 'lqz'
}
},
methods: {
handleClick() {
alert('美女')
}
},
props:['mymsg','age']
})
// 上面定义的子组件Header1,只能用在局部child里面
let vm = new Vue({
el: '#box',
data: {
msg: '我是父组件的数据',
age : 999
},
})
</script>
</html>
父传子之属性认证
将props写成对象的形式:key是变量名,value是数据类型
如果传的值,不是指定的数据类型,就会报错
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 在组件上自定义属性,使用属性指令,绑定好变量-->
<child :mymsg="msg" :age="age"></child>
<hr>
</div>
</body>
<script>
// 定义一个全局组件,在全局组件中定义一个局部组件
Vue.component('child', {
template: `
<div>
<h1>我是子组件---从父组件传值过来--{{ mymsg }}---{{ age }}</h1>
<br>
<button @click="handleClick">点我看美女--{{ name }}</button>
<hr>
</div>
`,
data() {
return {
name: 'lqz'
}
},
methods: {
handleClick() {
alert('美女')
}
},
props: {
mymsg: String,
age: Number
}// 写属性名字,就属性认证
})
// 上面定义的子组件Header1,只能用在局部child里面
let vm = new Vue({
el: '#box',
data: {
msg: '我是父组件的数据',
age: "999"
},
})
</script>
</html>
组件通讯之子传父(通过事件)
通过事件传,不能随件传。一般需要点击按钮子类的事件去传
实现一个在子组件中点击按钮,子组件按钮点击一下,整个组件就消失:父组件里面的变量isShow变成false
isShow是父组件的变量,但是点的是子组件的按钮
就是点的是子组件的按钮,让父组件消失,这样就实现了从子传父
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 通过自定义事件,绑定方法-->
<child v-if="isShow" @myevent="handleShow"></child>
<hr>
</div>
</body>
<script>
// 定义一个全局组件,在全局组件中定义一个局部组件
Vue.component('child', {
template: `
<div>
<h1>我是子组件</h1>
<br>
<button @click="handleClick">点我消失和显示</button>
<hr>
</div>
`,
data() {
return {
b: false
}
},
methods: {
handleClick() {
// 触发myevent的执行,把子组件的变量b,传入到事件对应的方法上
this.$emit('myevent',this.b)
}
},
})
// 上面定义的子组件Header1,只能用在局部child里面
let vm = new Vue({
el: '#box',
data: {
isShow: true,
},
methods: {
handleShow(b) {
this.isShow = b
}
}
})
</script>
</html>
捋一下逻辑
现在就是想点击子组件的时候,让子组件消失;通过自定义事件 <child v-if="isShow" @myevent="handleShow"></child>
@myevent是随便写的事件名,事件前面就是@符号。对着一个方法handleShow,handleShow是父组件里面的一个方法,再去父组件里面写这个方法
这里的handleShow传了一个参数,传不传都可以。让data里面的isShow等于b。
现在就相当于在父组件里面写了一个事件@myevent,并且给他绑定了一个方法handleShow
现在要做的是,点击子组件的button按钮的时候<button @click="handleClick">点我消失和显示</button>,触发子组件里面的methods里面的handleClick() 执行
在handleClick()里面触发父组件事件的执行:触发@myevent执行
这里是固定写法:this.$emit('myevent',this.b), this.b是参数。意思是触发myevent事件,把子组件中的变量b,传入到事件对应的方法上
ref属性
可以实现组件间通信。这个ref属性是Vue提供的
在Vue中通过this.$refs.属性值 拿到的是
如果放在普通标签上,拿到的就是普通标签本身(就是上面的input框,拿到input框就能点出name,value属性)
如果放在子组件上,拿到的就是子组件对象(如下)
通过组件对象,直接获取,修改属性,直接执行方法,传值,返回值
如上:this.$refs.mychild这个是子组件对象,this.$refs.mychild.b就是这个对象里面的属性
上面的是拿值,还可以改值。但是,直接改了,我们看不到。我们加一个v-if
通过父组件的点击,控制子组件的显示
上面除了可以改,可以打印子组件的值,还可以调用子组件的方法
用了这个之后发现:this.$refs.mychild,能拿到里面的对象了。里面的属性、方法就都可以拿到了。直接用、直接改就行了。有返回值的话,可以拿到(如下)
就不需要考虑是父传子,还是子传父了
也可以有结果,是在子组件里面return的数据,现在在父组件里面打印了出来
所以:用了ref属性之后,根本就不需要考虑子传父、父传子了。因为对象都能拿到了。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" ref="myinput" name="lqz">
<child ref="mychild"></child>
<hr>
<button @click="handleClick">点我试一下</button>
</div>
</body>
<script>
// 定义一个全局组件,在全局组件中定义一个局部组件
Vue.component('child', {
template: `
<div>
<h1 v-if="b">我是子组件</h1>
<br>
<button>点我消失和显示</button>
<hr>
</div>
`,
data() {
return {
b: true
}
},
methods: {
handle1(msg){
// alert(msg)
return 'xf'
}
},
})
// 上面定义的子组件Header1,只能用在局部child里面
let vm = new Vue({
el: '#box',
data: {
},
methods: {
handleClick(){
// console.log(this.$refs.myinput.name)
// console.log(this.$refs.mychild.b)
// this.$refs.mychild.b = !this.$refs.mychild.b
// 调用子组件的方法
let res = this.$refs.mychild.handle1('致命诱惑')
console.log(res)
}
}
})
</script>
</html>
动态组件
现在想要实现的是:点击上面的时候,下面就显示对应的组件
绑定事件就行
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 这里可以写简单的语法 "who='index'"-->
<span @click="who='index'">首页</span>  
<span @click="who='girl'">美女</span>  
<span @click="who='boy'">帅哥</span>  
<hr>
<!-- 加:是绑定;who是一个变量;根组件里面要有这个-->
<component :is="who"></component>
</div>
</body>
<script>
Vue.component('index', {
template: `<div>
首页
</div>`,
})
Vue.component('girl', {
template: `<div>
美女
</div>`,
})
Vue.component('boy', {
template: `<div>
帅哥
</div>`,
})
let vm = new Vue({
el: '#box',
data: {
who:'index'
},
methods: {}
})
</script>
</html>
keep-alive的使用
现在就想实现,当我切过来的时候,这个值还在
只需要用keep-alive包上这个组件就行了
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件化开发</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 这里可以写简单的语法 "who='index'"-->
<span @click="who='index'">首页</span>  
<span @click="who='girl'">美女</span>  
<span @click="who='boy'">帅哥</span>  
<hr>
<!-- 加:是绑定;who是一个变量;根组件里面要有这个-->
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
Vue.component('index', {
template: `<div>
首页
</div>`,
})
Vue.component('girl', {
template: `
<div>
美女
<input type="text" v-model="name">
</div>`,
data() {
return {
name: ""
} //在组件里面data必须是一个方法
}
})
Vue.component('boy', {
template: `<div>
帅哥
</div>`,
})
let vm = new Vue({
el: '#box',
data: {
who: 'index'
},
methods: {}
})
</script>
</html>
Vue脚手架创建Vue项目
我们现在想把前端做成一个项目,用到Vue脚手架
类似于工地上面盖楼的时候,先在搭上架子,再在固定地方填砖就行
Vue的脚手架:帮我创建一些空的文件,我需要在文件的固定地方填代码就行,其实就是一个框架(django创建的那个项目,也可以叫django的脚手架)
安装
先安装node
1、去node的官网:https://nodejs.org/zh-cn/ 下载node的解释器
2、直接下一步
装好了之后,就多了两个命令
node(类似于Python)
npm(类似于pip)
安装脚手架
1、npm install -g @vue/cli
-g :装全局
2、使用npm安装第三方模块,速度慢一些,换成淘宝镜像:cnpm(这个是在国内下载的)
先用npm下载cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
以后都用cnpm代替npm,做包管理
用cnpm安装脚手架
cnpm install -g @vue/cli
创建Vue项目
vue create 项目名
或
vue ui (图像化界面的创建)
vue ui
Bable:建项目之后,写一些新的语法(es6,es7),Bable把新的语法转成es5。主要是对低版本语法的兼容
Router:路由
Vuex:状态管理器
点击【保存预设并创建项目】
上面的是图形化界面创建,下面用命令行创建
vue create 项目名
在指定目录下敲:vue create mysecendvue
跟图形化界面是一样的
最后有点慢,是因为要去GitHub上面拉一个空的项目,没有网的话,别人拷贝也行
我们用pycharm开发Vue项目
这样项目就起来了。但是我们想向运行Python一下,点一下run就运行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。