今日内容概要
- 组件的补充知识
- 组件间通信之父传子
- ref属性
- 动态组件
- 插槽
- 计算属性
- 监听属性
- node环境搭建
今日内容详细
组件的补充知识
new Vue()对象后 管理的标签 叫做根组件
Vue.component() 创建出来的是全局组件 定义在其内部或vue对象内部的components产生的是局部组件
组件拥有自己的html css js包括各自的数据 事件等
在组件内部 this代指当前组件
父子组件的data是无法共享的
组件的data是一个函数 需要有返回值(return {})
组件间通信之父传子
由于组件间数据不共享 想要进行数据传递 那么需要一些方式
父传子:使用自定义属性的方式 自定义属性名不要使用驼峰体
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<h2>我是父组件 有一个子组件child</h2>
<child :myname="name"></child>
<!-- 注意 自定义属性的时候不要使用驼峰体 并且不要与子组件中的变量名起冲突 -->
<!-- <h1>属性验证 传入的必须是xx类型</h1>-->
<h2>字符串的age-->age="age"</h2>
<!-- <child myname="彭于晏" age="age"></child>-->
<h2>:age="19"的形式</h2>
<!-- <child :age="19" myname="彭于晏"></child>-->
<h2>age="19"的形式</h2>
<!-- <child age="19" myname="彭于晏"></child>-->
<h2>:age="age"的形式</h2>
<!-- <child :age="age" myname="彭于晏"></child>-->
</div>
<script>
var vm = new Vue({
el: '#app',
data:{name: 'lzj', age: 20},
components:{'child': {
template: `
<div>
<h1>我是子组件</h1>
<h2>姓名:{{myname}}</h2>
<h2>年龄:{{age}}</h2>
</div>
`,
data(){
return {age: 18}
},
// props:['myname'] // 需要接收需要的字段 如果父组件给子组件传了相同名字的数据 优先使用父组件的 后台会报错 不影响渲染
props:{myname: String, age:Number} // 指定数据类型 虽然指定了 但传的时候也可以是其他类型 并且正常渲染 但是后台会报错
}}
})
</script>
</body>
</html>
组件通信之子传父
子传父通过自定义事件的形式
并且自定义事件的名字也不能够使用驼峰体
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<br>
<h3>子组件发送的内容----input输入:{{mytext}} age:{{age}}</h3>
<br>
<child @childtxt="MyEvent"></child>
</div>
<script>
var child = {
template: `
<div>
<h1>我是子组件</h1>
<input type="text" v-model="mytext">
<!-- 可以通过事件触发发送 也可以在生命周期钩子函数中传递 -->
<button @click="childClick">点我发送</button>
</div>
`,
data() {
return {mytext: '', age:18}
},
methods: {
childClick() {
// 使用$emit触发父组件中的自定义事件 并将要传递父组件的数据传入
this.$emit('childtxt', this.mytext)
}
},
// 使用生命周期的钩子函数传递
updated(){
this.$emit('childtxt', this.mytext, this.age)
}
}
var vm = new Vue({
el: '#app',
data: {mytext: '', age: ''},
methods: {
// 自定义事件触发执行的函数 子组件发送几个就要接收几个
MyEvent(mytext, age) {
this.mytext = mytext
this.age = age
}
},
components: {
child
}
})
</script>
</body>
</html>
ref属性
自定义属性和自定义事件可以实现父子之间的传值 但还有一种方式可以更加方便的实现父子通信
ref属性
把ref属性放在普通标签上
通过this.$refs.ref属性值 拿到的是原生的dom对象 可以使用它来修改标签
把ref属性放在组件上
通过this.$refs.ref属性值 拿到的是组件对象 并且组件对象中的变量 方法等都能够取到
这样无论是子传父还是父传子 都可以通过组件对象直接使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<hr>
<h1>我是父组件</h1>
<h2>子组件的msg:{{msg}}</h2>
<hr>
<!-- 给子组件添加ref属性 -->
<child ref="childtext"></child>
<button @click="showChild">点我看子组件input</button>
</div>
<script>
var child = {
template: `
<div>
<h1>我是子组件</h1>
<h2>父组件的name:{{name}}</h2>
<input type="text" v-model="mytext">
</div>
`,
data() {
return {mytext: '', msg: '鸡你太美', name:''}
},
methods: {
showText(){
alert(this.msg)
}
},
}
var vm = new Vue({
el: '#app',
data: {msg: '', name: '蔡徐坤'},
methods: {
showChild(){
console.log(this.$refs)
// 通过this.$refs.childtext拿到该组件对象
// 可以取到组件对象的数据
alert(this.$refs.childtext.mytext)
// 也可以直接调用组件对象的函数
this.$refs.childtext.showText()
// 子传父
this.msg = this.$refs.childtext.msg
console.log(this.msg)
// 父传子
this.$refs.childtext.name = this.name
console.log(this.name)
// 之后无需关注子传父还是父传子 直接通过对象取值 赋值即可
}
},
components: {
child
}
})
</script>
</body>
</html>
动态组件
手动实现动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<!-- 通过点击事件 将对应组件名传入 并修改data中who的值 -->
<span @click="pageClick('home')">首页</span>
<span @click="pageClick('order')">订单</span>
<span @click="pageClick('goods')">商品</span>
<!-- 判断当前是哪个组件 来展示指定组件 -->
<home v-if="who === 'home'"></home>
<order v-else-if="who === 'order'"></order>
<goods v-else></goods>
</div>
<script>
// 定义三个局部组件
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`
}
var goods = {
template: `
<div>
<h1>goods页面</h1>
</div>`
}
var vm = new Vue({
el: '#app',
data:{
who: 'home'
},
methods:{
pageClick(who){
this.who = who
}
},
components:{
home,
order,
goods
}
})
</script>
</body>
</html>
使用动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<!-- 通过点击事件 将对应组件名传入 并修改data中who的值 -->
<span @click="pageClick('home')">首页</span>
<span @click="pageClick('order')">订单</span>
<span @click="pageClick('goods')">商品</span>
<!-- 通过component标签实现 无需手动写判断 当前的who是谁就展示 -->
<component :is="who"></component>
</div>
<script>
// 定义三个局部组件
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`
}
var goods = {
template: `
<div>
<h1>goods页面</h1>
</div>`
}
var vm = new Vue({
el: '#app',
data:{
who: home
},
methods:{
pageClick(who){
this.who = who
}
},
components:{
home,
order,
goods
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<!-- 通过点击事件 将对应组件名传入 并修改data中who的值 -->
<span @click="pageClick('home')">首页</span>
<span @click="pageClick('order')">订单</span>
<span @click="pageClick('goods')">商品</span>
<!-- 将动态组件包裹在keep-alive标签内 会保持组件的激活 切换动态组件的时候会保持切换前的状态 -->
<keep-alive>
<!-- 通过component标签实现 无需手动写判断 当前的who是谁就展示 -->
<component :is="who"></component>
</keep-alive>
</div>
<script>
// 定义三个局部组件
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`
}
var goods = {
template: `
<div>
<h1>goods页面</h1>
<input type="text">
<button>搜索</button>
</div>`
}
var vm = new Vue({
el: '#app',
data:{
who: home
},
methods:{
pageClick(who){
this.who = who
}
},
components:{
home,
order,
goods
}
})
</script>
</body>
</html>
插槽
一般情况下 编写完一个组件之后 组件的内容都是写死的 如果需要加载数据 那么只能去组件中修改 扩展性很差
继而出现了插槽的概念 只需要在组件中添加<solt></slot>标签 后续就可以在组件标签内部添加内容
与 django中的extend相似
匿名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<home>
<!-- 当前是匿名插槽 所以如果组件内部有多个匿名的slot 那么都会展示组件标签内扩展的所有内容 -->
<img src="333.jpeg" alt="">
</home>
</div>
<script>
var home = {
template: `
<div >
<h1>home组件</h1>
<!-- 添加slot标签 后续添加的内容在这块区域 -->
<slot></slot>
<hr>
<slot></slot>
<h1>home组件结束</h1>
</div>
`
}
var vm = new Vue({
el: '#app',
data:{},
components:{
home
}
})
</script>
</body>
</html>
具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<home>
<!-- 在对应标签中添加slot属性那么就会在指定插槽中展示 通常使用div包裹 这样无需添加多次该属性 -->
<div slot="a">
<img src="333.jpeg" alt="">
</div>
<!-- 多个标签使用并不会覆盖 而是会按照顺序依次往下 -->
<div slot="a">
<img src="222.jpeg" alt="">
</div>
</home>
</div>
<script>
var home = {
template: `
<div >
<h1>home组件</h1>
<!-- 给slot添加name属性 就变成了具名插槽 -->
<slot name="a"></slot>
<hr>
<slot name="b"></slot>
<h1>home组件结束</h1>
</div>
`
}
var vm = new Vue({
el: '#app',
data:{},
components:{
home
}
})
</script>
</body>
</html>
计算属性
计算属性只有使用的变量发生了变化时才会重新运算
和python中的property类似 可以把方法 函数 伪装成属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
体重:
<input type="text" v-model="weight">
身高:
<input type="text" v-model="height">
BMI:{{BMI}}
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
weight: '',
height: '',
},
// 计算属性写在computed中 以函数的形式 后续使用使用函数名即可
computed:{
BMI(){
console.log('计算属性执行了')
if (this.weight && this.height){
return (this.weight / Math.pow(this.height, 2)).toFixed(1)
}else {
return 0
}
}
}
})
</script>
</body>
</html>
基于计算属性重写过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script src="axios/axios.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="myText">
<ul>
<!-- 直接使用计算属性的返回值 -->
<li v-for="i in textInput">
{{i}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data:{
myText: '',
dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
},
methods: {},
computed:{
textInput(){
// 该计算属性中使用了input框的myText 是双向绑定的数据 会变化 也就会重复调用该方法
return this.dataList.filter(item => item.indexOf(this.myText) >= 0)
}
}
})
</script>
</body>
</html>
监听属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<link rel="stylesheet" href="bootstrap-3.4.1-dist/css/bootstrap.min.css">
<!-- <script src="bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>-->
<script src="axios/axios.js"></script>
</head>
<body>
<div id="shop">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">购物车</h1>
<!-- 通过事件冒泡处理切换用户 清空选择列表及全选 -->
<div @click="new_list=[]" style="width: 110px">
<div @click="all=false">
<!-- 给按钮绑定点击事件 点击不同按钮user_id是不同的值 -->
<button @click="user_id=i.car" v-for="i in all_user">{{i.name}}</button>
</div>
</div>
<div v-if="user_id">
<table class="table table-hover" >
<thead>
<tr>
<th>商品编号:</th>
<th>商品名:</th>
<th>数量:</th>
<th>单价:</th>
<th><span v-if="all">取消全选</span>
<span v-else>全选</span>
<input type="checkbox" v-model="all" @click="allClick">
</th>
</tr>
</thead>
<tbody>
<tr v-for="(goods, index) in goods_list">
<th scope="row">{{index + 1}}</th>
<td>{{goods.name}}</td>
<td>
<button @click="clickDown(goods, index)">-</button>
{{goods.num}}
<button @click="clickUp(goods)">+</button>
</td>
<td>{{goods.price}}</td>
<td>
选择<input type="checkbox" v-model="new_list" :value="goods" @change="goodsClick">
</td>
</tr>
</tbody>
</table>
<h2>总价{{allMoney}}</h2>
</div>
</div>
</div>
</div>
</div>
<script>
var vm = new Vue({
el: '#shop',
data: {
goods_list: [{name: '保时捷', num: 2, price: 999, stock: 10}, {
name: '法拉利',
num: 3,
price: 1000,
stock: 8
}, {
name: '兰博基尼',
num: 1,
price: 1000,
stock: 12
}],
new_list: [],
all: false,
user_id: ''
},
methods: {
clickUp(good) {
if (good.num < good.stock) {
good.num++
} else {
alert(`库存不足` + good.stock)
}
},
clickDown(good, index) {
if (good.num > 1) {
good.num--
} else {
var yes = confirm('再减就删除了 确定吗')
if (yes) {
for (i in this.new_list) {
if (this.new_list[i] === good) {
this.new_list.splice(i, 1)
}
}
this.goods_list.splice(index, 1)
}
}
},
goodsClick() {
if (this.new_list.length === this.goods_list.length) {
this.all = true
} else {
this.all = false
}
},
// 全选
allClick() {
if (this.all) {
this.new_list = []
} else {
this.new_list = this.goods_list
}
},
// 从后端获取数据函数
getData(a) {
// 判断用户id是否有值 有值再去后端取数据
if (this.user_id) {
axios.get('http://127.0.0.1:8000/shop_car/' + a + '/').then(res => {
this.goods_list = res.data.shop_car
})
}
}
},
// 计算属性
computed:{
allMoney(){
var all = 0
for (i of this.new_list) {
all += i.price * i.num
}
return all
}
},
// 监听属性 内部填写以被监听属性为名字的函数 一旦对应属性被修改 就会执行对应函数
watch:{
user_id(){
// 传进去的是要查看用户的购物车id
this.getData(this.user_id)
}
},
// 生命周期钩子函数
created() {
axios.get('http://127.0.0.1:8000/user/').then(res => {
this.all_user = res.data
}
})
</script>
</body>
</html>
node环境搭建
# Vue-CLI 项目搭建
-vue 脚手架 可以创建vue项目
# vue脚手架必须要按照 node js 解释型语言
-node js是一门后端语言
-JavaScript只能运行在浏览器中,因为浏览器中有他的解释器环境
-基于谷歌浏览器的v8引擎(js解释器),使它能够运行在操作系统上
-文件操作
-网络操作
-数据库操作 模块
-nodejs 解释器环境
-http://nodejs.cn/ 下载对应平台的nodejs解释器
-一路下一步安装
-安装完成会有两个可执行问题
python node
pip npm
-打开cmd
node 进入到了node环境
npm install 装模块
标签:age,var,vue5,new,组件,home,data
From: https://www.cnblogs.com/lzjjjj/p/17131612.html