父子组件传值
父组件向子组件传值
//html //1.父组件通过v-bind给子组件传值 <todo-item v-bind:content="data1"></todo-item> //script //定义全局组件 Vue.component("TodoItem", { //2.子组件通过props接收 props: ['content'] //也可以用对象形式进行参数校验 //props: {content: String}//只允许接受string template: "<li>{{content}}</li>" }) var app = new Vue({ ... data: { data1: "ted" } })子组件向父组件传值
//html //2.父组件使用子组件时,通过v-on监听触发的事件 //一旦子组件delete触发,就会触发父组件handleItemDelete这个方法 <todo-item v-on:delete="handleItemDelete"> </todo-item> //script var TodoItem = { data: { data1: 'ted' }, template: "<li v-on:click='handleButtonClick'>点我删除</li>", methods: { handleButtonClick: function() { //1.子组件通过$emit向外触发delete事件,并传出data1 this.$emit("delete", data1) } } } var app = new Vue({ ... methods: { //3.父组件使用子组件的值 handleItemDelete: function(data1) { alert("data1") } } })
非父子组件传值
观察者模式
<!-- 非父子组件传值 --> <!-- 通过观察者模式实现,两个子组件之间传值,点击其中一个组件,另一个组件的值变成这个被点击组件的值--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./vue.js"></script> </head> <body> <div id="root"> <child :content="content1"></child> <child :content="content2"></child> </div> <script> //1. 在Vue的prototype上定义一个bus Vue.prototype.bus = new Vue() Vue.component('child', { props: { content: String }, template: '<div v-on:click="handleClick">{{content}}</div>', methods: { handleClick: function() { //使用bus向外触发事件 this.bus.$emit('change', this.content) } }, //利用钩子函数,监听change事件 mounted: function() { var this_ = this this.bus.$on('change', function(msg) { this_.content = msg }) } }) var vm = new Vue({ el: "#root", data: { content1: "tedqin", content2: "teddymoon" } }) </script> </body> </html>- vuex
全局组件和局部组件
全局组件:用Vue.component()方法定义,其他组件可以直接使用
//html //父组件通过v-bind给子组件传值 <todo-item v-bind:content="data1"></todo-item> //script //定义全局组件 Vue.component("TodoItem", { //子组件通过props接收 props: ['content'] template: "<li>{{content}}</li>" }) var app = new Vue({ ... data: { data1: "ted" } })局部组件:像普通对象一样定义,其他组件引用的时候需要注册
//html //父组件通过v-bind给子组件传值 <todo-item v-bind:content="data1"></todo-item> //script //定义局部组件 var TodoItem = { props: ['content'] template: "<li>{{content}}</li>" } var app = new Vue({ ... //把局部逐渐注册到到需要引用它的组件的vue实例中 components: { TodoItem: TodoItem } data: { data1: "ted" } })
v-bind,v-model,v-for和v-on
v-bind:用于给标签/组件绑定属性,实现动态管理标签的属性
//html <a v-bind:href="url">网络测试</a> //v-bind绑定href //script var app = new Vue({ ... data { url: "http://www.baidu.com" } })//html //父组件通过v-bind给子组件传值 <todo-item v-bind:content="data1"></todo-item> //script Vue.component("TodoItem", { //子组件通过props接收 props: ['content'] template: "<li>{{content}}</li>" }) var app = new Vue({ ... data: { data1: "ted" } })v-model:实现数据和视图层的双向绑定,只能定义在input,select,textarea上,绑定之后随着input输入的变化,对应绑定的内容也变化,反之也变化
//html <input type="text" v-model="inputValue" /> //script var app = new Vue({ ... data: { inputValue: '' } })v-for:循环data
//循环数组 //html <li v-for="item of list">{{item.text}}</li> <li v-for="(item, index) of list">{{item.text}}---{{index}}</li> <li v-for="(item, index) of list" :key="item.id">{{item.text}}---{{index}}</li> <!--用index的时候最好再用key唯一标识--> //script var app = new Vue({ ... data: { list: [{ id: "1", text: "ted" }, { id: "2", text: "xxy" }] } })//循环对象 //html <li v-for="(item, key, index) of list">{{item}}--{{key}}--{{index}}</li> <!--输出"ted--name--0 23--age--1"--> //script var app = new Vue({ ... data: { list: { name: "ted", age: "23" } } })v-on:绑定事件
//html <button v-on:click="handleButtonClick">提交</button> //script var app = new Vue({ ... methods: { handleButtonClick: function() { alert("click!") } } })
v-text和v-html的区别
- v-text: 等同于插值表达式双括号,绑定当前元素的innerText,会原封不动的输出纯文本
v-html: 绑定当前元素的innerText,会以html规则编译文本内容后输出
//html <div v-text="name"></div> <!--输出<h1>ted</h1>--> <div v-html="name"></div> <!--输出h1大小的ted--> //script var vm = new Vue({ el:"#app", data: { name:"<h1>ted</h1>" } })
计算属性 computed
和逻辑有关的计算都放在computed中,不方便直接在模版中计算
例子:
get属性
<div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } })set属性
computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } }
上面代码中,get作用是通过监听firstName和lastName的改变,获取fullName的值;
set的所用是传入需要改变的fullName,并根据参数更新firstName和lastName的值
- 和method的不同:
- 计算属性中的值依赖data中相关联的值
- computed存在缓存机制:每次重新渲染时,对于method,每次都会重新计算;对于计算属性,仅当data中依赖的值改变时,计算属性的值才改变,
侦听器 watch
和computed相似,同样是监听data中的值,当data发生改变时,执行相应的操作
也具有缓存效果
- 和computed的不同:
- computed是定义并计算一个新的值,这个值依赖data中的某些值
- watch是监听data中已经存在的变量,并在data发生改变的时候做相应的操作
- computed比watch更加简洁
样式绑定
class绑定:
:class=等价于: v-bind:class=,将class绑定在一个标签上,可以控制class的显示与否class的对象绑定
:class="{activated: isActivated}"<style> .activated {color: red} </style> <div @click="handleDivClick> :class="{activated: isActivated}"></div> var vm = new Vue({ el: "#app", data: { isActicated: false }, method: { handleDivClick: function() { this.isActivated = true } } })- class的数组绑定
:class="[activated]"
```
<style>
.activated {color: red}
</style>
<div @click="handleDivClick>
:class="{activated: isActivated}"></div>
var vm = new Vue({
el: "#app",
data: {
activated: ""
},
method: {
handleDivClick: function() {
this.activated = "activated"
}
}
})
```
内联样式绑定
style的对象绑定
<div :style="styleObj" v-on:click="handleDivClick"></div> var vm = new Vue({ el: "#app", data: { styleObj: { color: red } }, methods: { handleDivClick: function() { this.styleObj.color = red } } })style的数组绑定
只需要把
<div :style="styleObj"换成<div :style=[styleObj, {fontSize: '20px'}]
条件渲染
- v-if: 隐藏的元素不会被渲染到页面上,还可以用v-else
v-show: 隐藏的元素已经被渲染到页面上,只是用了display:none来隐藏
<div v-if="show">{{name}}</div> <div v-else="show">Bye</div> <div v-if="show===a">a</div> <div v-else-if="show===b">b</div> <div v-else>bye</div> <div v-show="show">{{name}}</div> var vm = new Vue({ el: "#app", data: { name: 'ted', show: false }, })
vue中的set方法
arr=[1,2,3,4,5]
data={
name: "ted",
age: "23"
}
改变页面中的渲染出来的对象或数组,不能直接用arr[3]=5这样直接改,只能修改数组/对象的引用,即this.arr=[1,2,5,4,5]全部修改
也可以用Vue.set()方法修改,set方法也可以添加新的数据
//改数组 Vue.set(this.arr, 0, 11) //[11,2,3,4,5] //改对象 Vue.set(this.data, "name", "teddy") //{name:"teddy", age: "23"}
slot插槽:
父组件向子组件传递dom结构: 直接在子组件中定义,然后在template中引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<child>
<h1>tedqin</h1>
</child>
</div>
<script>
Vue.component('child', {
template: `<div>
<p>hello</p>
<slot></slot>
</div>
`
})
var vm = new Vue({
el: "#app"
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<child>
<header slot="header"></header>
<footer slot="footer"></footer>
</child>
</div>
<script>
Vue.component('child', {
template: `<div>
<slot name="header"></slot>
<p>hello</p>
<slot name="footer"></slot>
</div>
`
})
var vm = new Vue({
el: "#app"
})
</script>
</body>
</html>
动态组件
<component :is="type"></component>
//
Vue.component('type1', {
template: '<div>type1</div>'
})
Vue.component('type2', {
template: '<div>type2</div>'
})
//
data:{
type: 'type1'
}
//
methods: {
handleBtnClick: function(){
this.type = (this.type==="type1" ? 'type2' : 'type1')
}
}
根据is属性绑定的data数据中的type动态切换组件
v-once
将第一次展示在页面中的资源保存在内存中,下次直接从内存中取资源,可以优化性能,提高静态页面展示效率
##vue的路由
src/main.js
入口文件,定义了一个根实例
import Vue from 'vue' import App from './App' import router from './router' new Vue({ el: "app", //app挂载点在./index.html上 router, //使用router,在路由配置文件index.js中配置路由 components: { App }, //使用子组件App template: '<App/>' //渲染App这个局部组件 })
src/App.js
App局部组件,也就是main.js渲染的页面,也就是主页面
<template> <div id="app> <router-view> //显示当前路由地址所对应的路由内容 </div> </template> <script> export default { name: 'App' } <sctipt> <style> #app { ... } <style>
src/router/index.js
路由配置项
`
import Vue from ‘vue’
import Router from ‘vue-router’
import Home from ‘@/pages/home/Home’
import Home from ‘@/pages/list/List’
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', //1.当用户访问根路径的时候
name: 'Home',
components: Home // 2.访问home这个单文件组件
}, {
//增加其他页面的配置项
path: '/list',
name: 'List',
components: List
}
]
})
```
@/pages/home/Home.vue
主页,单文件组件
<template> <div>home</div> </template> <script> export default { name: 'Home' } </script> <style> </style>
@/pages/list/List.vue
list页面,单文件组件
<template> <div>list</div> </template> <script> export default { name: 'List' } </script> <style> </style>
vue是单页面应用,用替换a标签
<router-link to="/list">点击跳转</router-link>