Vue
组件
- 组件是(Component)是Vue.js 最红要的功能之一。
- 组件可以扩展HTML元素,封装可重用的代码
- 组件系统还可以用独立,可复用的小组件来构建成大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树。
- 注册全局组件语法:
Vue.component('组件名','配置选项')
- 注册成功之后,使用下面的方法调用组件:
<tagName></tagName>
全局组件
所有实例都能用全局组件
#注册一个简单的全局组件并使用它
<div id="app">
<runoob></runoob>
</div>
<script>
// 注册
Vue.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用
# 注册一个简单的局部组件 runnoob ,并使用它:
<div id="app">
<runoob></runoob>
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
components: {
// <runoob> 将只在父模板可用
'runoob': Child
}
})
</script>
组件中的一些小知识点:
根组件和其他组件的一些问题
- new Vue() 管理的是自己挂载的div,也就是根组件
- 自己定义的全局和局部,都是组件
- 组件都有自己的HTML,css,js ,事件,数据
- 在组件中this是指,当前的组件
- 父子组件的data是无法共享的
- data是一个函数,需要有返回值(return)
组件之间的通信
- 组件之间通信使用的 是prop
- prop是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来。
组件之间父传子的通信
# 上面我们讲过组件间的数据是不能共享的,想要共享就需要数据传递
1.可以通过自定义属性来进行传递
2.子组件使用prop来接收父组件传递过来的数据
3.父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop"
4.可以用v-bind 动态绑定props的值到父组件的数据中。每当父组件的数据的变化时,这个变化也就会传给子组件。
<div class="app">
<h1>父子通信之父传子,通过自定义属性--->不能用驼峰,不要跟子组件中变量冲突</h1>
<!-- <h2>字符串的age–>age="age"</h2>-->
<!-- <child age="age"></child>-->
<!-- <h2>:age="19"</h2>-->
<!-- <child :age="19"></child>-->
<!-- <h2>age="19"</h2>-->
<!-- <child age="19"></child>-->
<!-- <h2>:age="age"</h2>-->
<child :age="age" myname="彭于晏"></child>
<h1>属性验证---》传入的必须是xx类型</h1>
<!-- <h2>字符串的age–>age="age"</h2>-->
<!-- <child age="age"></child>-->
<!-- <h2>:age="19"</h2>-->
<!-- <child :age="19"></child>-->
<!-- <h2>age="19"</h2>-->
<!-- <child age="19"></child>-->
<!-- <h2>:age="age"</h2>-->
<!-- <child :age="age"></child>-->
</div>
<script>
// 父中有age,子child 只有name,没有age,现在把父中的age传到child中,显示
var child = {
template: `
<div>
<button>后退</button>
首页--->名字:{{ myname }}--->年龄:{{ age }}
<button>前进</button>
</div>`,
data() {
return {
myname: 'lqz'
}
},
// props: ['age'],
props: {age: Number, myname: String},
}
var vm = new Vue({
el: '.app',
data: {
age: 19
},
components: {
child
}
})
</script>
</html>
组件之间子传父
1.通过自定义事件来进行数据的传递
2.可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
3.父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
案例:
<body>
<div class="app">
<p>子组件传递过来的数据: {{mytext}}</p>
<hr>
<child @myevent="handleEvent"></child>
<hr>
</div>
</body>
<script>
var child = {
template: `
<div>
<input type="text" v-model="mytext">
<button @click="handleSend">点我传递</button>
</div>`,
data() {
return {
mytext: ''
}
},
methods: {
handleSend() {
// alert(this.mytext)
// 子组件中,触发自定义事件的执行,会执行父组件自定义事件绑定的函数,有几个参数,就传几个参数
this.$emit('myevent', this.mytext)
}
}
}
var vm = new Vue({
el: '.app',
data: {
mytext: ''
},
methods: {
handleEvent(mytext) {
this.mytext = mytext
}
},
components: {
child
}
})
</script>
</html>
prop 验证
-
组件可以在props中指定验证要求
-
定制prop的验证方式,可以为prop中提供一个带
有验证需求的对象,而不是一个字符串数组。
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
ref 属性
- 不管是自定义属性和自定义事件,可以实现父传子传值
- ref 属性,可以实现方便的实现父子通信
- ref属性放在普通标签上
- 通过this.$refs.myinput 拿到的是原生DOM对象,通过原生DOM修改标签
- ref 属性放在组件上,
- 通过this.$refs.mychild 拿到的是组件对象,既然拿到组件对象,组件对象中的变量,方法。都能直接通过
.
的方式调用 - 因此不需要关注是子传父还是父传子 ,直接通过组件对象,使用即可。
- 通过this.$refs.mychild 拿到的是组件对象,既然拿到组件对象,组件对象中的变量,方法。都能直接通过
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<button @click="handleClick">点我</button>
----》{{age}}
<br>
<input type="text" ref="myinput">
<div ref="mydiv">我是div</div>
<hr>
<child ref="mychild"></child>
<hr>
</div>
</body>
<script>
// 父中有age,子child 只有name,没有age,现在把父中的age传到child中,显示
var child = {
template: `
<div>
<h1>名字:{{ name }}--->年龄:{{ age }}</h1>
<button @click="handleClick">点我弹出名字</button>
</div>`,
data() {
return {
name: 'lqz',
age: 19
}
},
methods: {
handleClick() {
alert(this.name)
} } }
var vm = new Vue({
el: '.app',
data: {
age: 999,
},
methods: {
handleClick() {
// 1 ref 属性放在普通标签上,拿到标签的dom对象
// 通过this.$refs可以拿到所有标签上写了ref属性的 标签 ,对象类型 key值是ref对应的value值, value值是原生dom对象
// console.log(this.$refs)
// 直接修改原生dom对象的value属性,input就能看到有值了
// this.$refs.myinput.value = 'lqz is handsome'
//2 ref 属性放在 组件上,拿到的是 组件对象 ,就可以使用组件对象的属性和方法
// console.log(this.$refs) // 对象中有3个值,两个普通标签,一个组件
// this.$refs.mychild 就是组件对象,可以 .属性, .方法
// this.age = this.$refs.mychild.age
// 重点:以后就不需要关注是子传父还是父传子了,直接通过对象取值赋值即可,而且可以主动调用子组件中的函数
this.$refs.mychild.handleClick()
}
},
components: {
child
}
})
</script>
</html>
动态组件
<div class="app">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<component :is="who"></component>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
who: 'home'
},
methods: {
handleClick(type) {
this.who = type
}
},
components: {
home,
order, goods
}
})
</script>
keep-alive 保持钻进不被销毁
- 简单来说就是但我们执行一到程序,中途切换到其他的程序代码,执行的这个代码保持不被取消,返回还能继续基于上一次执行的作业。
# 一般止痒的情况都是在搜索的情况下应用
<body>
<div class="app">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
<input type="text" > <buttont>搜索</buttont>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
who: 'home'
},
methods: {
handleClick(type) {
this.who = type
}
},
components: {
home,
order, goods
}
})
</script>
</html>
插槽
概念:
- 在一般情况下,编写完一个组件之后,组件的内容都是写死的,需要加数据只能去组件中修改,扩展性很差
- 然后就出现了插槽这个概念,只需要在组件中
这个标签,就可以在body中的组件标签中添加内容。 - 插槽分为两种
- 匿名插槽,具名插槽
匿名插槽:
# 使用匿名插槽,在不同的地方使用同一个组件的情况下,还是可以的。但是如果想要使用不一样的插件的话,就需要带上标识了。下面会讲。
<body>
<div class="app">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
<input type="text" > <buttont>搜索</buttont>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
who: 'home'
},
methods: {
handleClick(type) {
this.who = type
}
},
components: {
home,
order, goods
} })
</script>
</html>
具名插槽
上面讲过,在使用插槽的时候如果想要使用不同的插槽就需要给插槽加上不一样的标识,我们可以通过给标签上加上一个name的属性来表示。
<body>
<div class="app">
<hr>
<home>
<div slot="a">
<img src="./img.png" alt="">
</div>
<div slot="b">
我是div
</div>
</home>
<hr>
</div>
</body>
<script
var home = {
template: `
<div>
<h1>home页面</h1>
<slot name="a"></slot>
<h1>结束了</h1>
<slot name="b"></slot>
</div>`
}
var vm = new Vue({
el: '.app',
data: {},
components: {
home,
}
})
</script>
</html>
计算属性
- 计算属性的关键字:computed
- 计算属性对于处理一些复杂逻辑时是很有用的
- 计算属性只有在使用的变量发生变化时,才会重新运算
- 计算属性就像是python中property,可以把方法/函数伪装成属性
计算属性基本使用
<body>
<div class="app">
<!-- <h1>input输入单词,首字母转成大写展示</h1>-->
<!-- <input type="text" v-model="mytext">--–>{{mytext.slice(0, 1).toUpperCase() + mytext.slice(1)}}-->
<h1>input输入单词,首字母转成大写展示---函数方式---》只要页面刷新,无论跟它有没有关,都会重新运算</h1>
<!-- <input type="text" v-model="mytext">--–>{{getUpper()}}-->
<input type="text" v-model="mytext">---->{{newText}}
<br>
<input type="text" v-model="age">--->{{age}}
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
mytext: '',
age: 10
},
methods: {
getUpper() {
console.log('函数---我执行了')
return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(1)
}
},
// 计算属性---->computed 里面写方法,以后,方法当属性用 ,一定要有return值
computed: {
newText() {
console.log('计算属性---我执行了')
return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(1)
}} })
</script>
通过计算属性重写过滤案例
<body>
<div>
<div class="app">
<h1>过滤案例</h1>
<p>请输入要搜索的内容:<input type="text" v-model="myText"></p>
<ul>
<li v-for="item in newDateList">{{item}}</li>
</ul>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
myText: '',
dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
},
computed: {
newDateList() {
return this.dataList.filter(
item => item.indexOf(this.myText) >= 0
)
}
}
})
</script>
监听属性
# 当在data中定义了一些变量,只要变量发生了变化,我们就会执行一个函数
watch:{
属性名(){
}
}
案例:
<body>
<div>
<div class="app">
<!-- <span @click="handleClick(1)">Python</span>| <span @click="handleClick(2)">Linux</span>-->
<span @click="course_type=1">Python</span>| <span @click="course_type=2">Linux</span>
<div>
假设有很多课程,点击上面的标签可以完成过滤
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
course_type: '0'
},
created() {
this.getData()
},
methods: {
getData() {
// 发送ajax ,获取所有课程,通过course过滤
// http://127.0.0.1:8080/api/v1/courses?course_type=0
},
// handleClick(type){
// this.course_type=type
// this.getData()
// }
},
watch: {
course_type() {
console.log('我变化了')
this.getData()
}
}
})
</script>
</html>
标签:Vue,05,--,age,var,组件,属性
From: https://www.cnblogs.com/qiguanfusu/p/17131322.html