DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>初识Vuetitle>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="demo">
<h1>Hello,我叫{{name}},来自{{address}}!h1>
div>
<script type="text/javascript" >
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//创建Vue实例
new Vue({
el:'#demo', //全称`element` 用来绑定所创建容器的`DOM` 对象(不仅仅可以通过`id` 选择器绑定)
data:{ //存储数据供绑定的容器获取对应的值
name:'mtf',
address:'河南'
}
})
script>
body>
html>
id
选择器进行容器的绑定)el
:全称element
用来绑定所创建容器的DOM
对象(不仅仅可以通过id
选择器绑定)data
:存储数据供绑定的容器获取对应的值模板语法主要分为:插值语法
{{参数或者js表达式}}
和指令语法(用于解析标签,包括:标签属性、标签体内容、绑定事件…)
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>模板语法title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>插值语法h1>
<h3>你好,{{name}}!h3>
<hr/>
<h1>指令语法h1>
<a v-bind:href="school.url.toUpperCase()">点我去{{school.name}}官网学习a>
<br>
<br>
<a :href="school.url">点我还去{{school.name}}官网学习a>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'mtf',
school:{
name:'aynu',
url:'http://www.aynu.edu.cn/',
}
}
})
script>
html>
{{xxx}}
中的xxx可以是data
中的数据,也可以是js表达式,且xxx可以自动读取到data中的所有属性;v-bind:href="xx"
:引号中的xx
可以data
中的参数也可以是表达式,参考上面示例Vue中的数据绑定主要分为单向数据绑定和双向数据绑定
什么叫单向数据绑定:用户不能通过前端页面输入的值来改变前端代码里面的
data
所对应的值(需要进一步总结)
单向数据绑定:<input type="text" v-bind:value="name"><br/>
单向数据绑定:<input type="text" :value="name"><br/>
什么叫双向数据绑定:浏览器页面的数据能够从后台代码获取,同时也可以通过修改浏览器页面的数据并响应到后台
v-model
指令语法只适用于表单标签(这样记:因为只有表单能够让我们在前端浏览器输入数据,才具备浏览器数据修改并响应到后台的前提条件)
双向数据绑定:<input type="text" v-model:value="name"><br/>
双向数据绑定:<input type="text" v-model="name"><br/>
el
和data
两种写法//el的两种写法
const v = new Vue({
//el:'#root', //第一种写法
data:{
name:'mtf'
}
})
console.log(v)//Vue实例对象
v.$mount('#root') //第二种写法
//data的两种写法
new Vue({
el:'#root',
//data的第一种写法:对象式
data:{
name:'尚硅谷'
} ,
//data的第二种写法:函数式
data(){
console.log('@@@',this) //此处的this是Vue实例对象
return{
name:'mtf'
}
}
})
defineProperty
<script type="text/javascript" >
let number = 18
let person = {
name:'张三',
sex:'男',
}
//给person对象添加一个age属性
Object.defineProperty(person,'age',{
value:18
})
console.log(person)
</script>
注意:上述js代码虽然能够给已经创建的对象临时添加对应的属性,可是不能通过控制台修改age
属性的值
这里查阅资料了解Object.defineProperty
方法有几个可配置的属性参数
writable:true //控制属性是否可以被修改,默认值是false
enumerable:true, //控制属性是否可以枚举,默认值是false
configurable:true //控制属性是否可以被删除,默认值是false
场景:假设设置一个number
变量,将变量中的值动态的赋值给age
属性,并且能够通过控制台动态的修改age
属性的值
<script type="text/javascript" >
var number = 18
let person = {
name:'张三',
sex:'男',
}
//给person对象添加一个age属性
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true, //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('有人读取age属性了')
return number![给age属性赋值](E:\java\Vue\笔记图片\给age属性赋值.png)
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
})
// console.log(Object.keys(person))
console.log(person)
</script>
什么叫数据代理?数据代理就是对一个对象或对象属性值的修改等一些操作的行为“委托”给它的代理对象来做。就比如说上述实例中
person
对象的age
属性,对age
属性一系列的操作交给了Object
对象,Object
对象调用defaultProperty
方法操作age属性
Vue
中的数据代理DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue中的数据代理title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'aynu',
address:'安阳'
}
})
console.log(vm)
script>
html>
总结:
vm
代理对象我么能够更加方便的操作data
中的数据DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件的基本使用title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习h2>
<button v-on:click="showInfo">点我提示信息button>
<button @click="showInfo1">点我提示信息1(不传参)button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
},
methods:{
showInfo(event){
console.log(this)
alert("我是傻子!")
},
showInfo1(event){
console.log(this) //此处的this是vm
alert('mtf你好!')
},
showInfo2(event,number){
console.log(event,number)
console.log(this) //此处的this是vm
alert('mtf你好!!')
}
}
})
script>
html>
常用事件修饰符:
prevent
once
stop
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息a>
<div class="demo1" @click="showInfo1">
<button @click.stop="showInfo">点我提示信息button>
div>
<button @click.once="showInfo">点我提示信息button>
绑定指定键盘按键事件
<div id="root">
<input type="text" placeholder="回车" @keydown.enter="showInfo">
div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'mtf'
},
methods: {
showInfo(e){
console.log(e.key,e.keyCode)
console.log(e.target.value)
alert("我按回车啦!")
}
},
})
script>
<div id="root">
<input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.config.keyCodes.huiche = 13 //定义了一个别名按键(需要知道指定按键对应的Code值)
new Vue({
el:'#root',
data:{
name:'mtf'
},
methods: {
showInfo(e){
//控制台输出指定按键对应的Code值
console.log(e.key,e.keyCode)
console.log(e.target.value)
alert("我按回车啦!")
}
},
})
script>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}span> <br/><br/>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
demo(){
}
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
console.log('get被调用了')
// console.log(this) //此处的this是vm
return this.firstName + '-' + this.lastName
},
//set什么时候调用? 当fullName被修改时。
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
script>
html>
下面的代码也能够满足开发的需求(在methods中定义一个计算属性的方法)
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
//注意:这里插值语法中直接调用的是下面定义的`fullName()`函数,得到的是函数的返回值
全名:<span>{{fullName()}}span>
div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
return this.firstName + '-' + this.lastName
}
},
})
script>
总结:与上述计算属性相比二者的优缺点
computed:{
//完整写法
/* fullName:{
get(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
},
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
} */
//简写
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//简写
/* isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
}
})
// vm.$watch('isHot',{
// immediate:true, //初始化时让handler调用一下
// //handler什么时候调用?当isHot发生改变时。
// handler(newValue,oldValue){
// console.log('isHot被修改了',newValue,oldValue)
// }
// })
script>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_深度监视title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
<hr/>
<h3>a的值是:{{numbers.a}}h3>
<button @click="numbers.a++">点我让a+1button>
<h3>b的值是:{{numbers.b}}h3>
<button @click="numbers.b++">点我让b+1button>
<button @click="numbers = {a:666,b:888}">彻底替换掉numbersbutton>
{{numbers.a}}
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:1,
c:{
d:{
e:100
}
}
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
// immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//监视多级结构中某个属性的变化
'numbers.a':{
handler(){
console.log('a被改变了')
}
},
//监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
}
})
script>
html>
总结:
计算属性能做的监视属性一定能做!但是监视属性能做的计算属性不一定能做!
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_watch实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}span> <br/><br/>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
firstName(val){
setTimeout(()=>{
console.log(this)
this.fullName = val + '-' + this.lastName
},1000);
},
lastName(val){
this.fullName = this.firstName + '-' + val
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>绑定样式title>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
style>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeMood">{{name}}div> <br/><br/>
<div class="basic" :class="classArr">{{name}}div> <br/><br/>
<div class="basic" :class="classObj">{{name}}div> <br/><br/>
<div class="basic" :style="styleObj">{{name}}div> <br/><br/>
<div class="basic" :style="styleArr">{{name}}div>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:false,
atguigu2:false,
},
styleObj:{
fontSize: '40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
methods: {
changeMood(){
const arr = ['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
},
})
script>
html>
一般用来通过逻辑表达式中是否为真来控制容器标签的显示与隐藏
v-if="表达式"
v-show="表达式"
二者之间的区别:
v-else-if
和v-else
连用,但是注意他们彼此之间结构不能被打断,并且隐藏的DOM是直接被移除的DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本列表title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>人员列表(遍历数组)h2>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}
li>
<hr>
<li v-for="(p,pid) of persons" :key="p.id">
{{p.name}}-{{p.age}}-{{pid}}
li>
ul>
div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
]
})
script>
html>
注意:v-for
指令语法的使用
v-for="(p,index) of persons"
:persons
代表要遍历的数组(对象,集合等),p
代表遍历数组中的一个元素,index
代表虚拟DOM对象标识(尽量不要使用)可以选择使用数据中的唯一标识,例如:id…(Vue中key的比较原理)收集表单数据
将收集的表单数据转换成JSON字符串
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>收集表单数据title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
密码:<input type="password" v-model="userInfo.password"> <br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
<br/><br/>
所属校区
<select v-model="userInfo.city">
<option value="">请选择校区option>
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option value="shenzhen">深圳option>
<option value="wuhan">武汉option>
select>
<br/><br/>
其他信息:
<textarea v-model.lazy="userInfo.other">textarea> <br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》a>
<button>提交button>
form>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:18,
sex:'female',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
script>
html>
定义:对显示的数据进行格式化处理
过滤器定义方式两种:
- 全局过滤器
- 局部过滤器
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>过滤器title>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="../js/dayjs.min.js">script>
head>
<body>
{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
-->
<div id="root">
<h3>现在是:{{time | FormatMyTime}}h3>
<h3>现在是:{{time | FormatMyTime('YYYY_MM_DD') | mySlice}}h3>
<h3 :x="msg | mySlice">尚硅谷h3>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//注册全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
new Vue({
el:'#root',
data:{
time:Date.now(), //获取当前系统时间戳
msg:'你好,mtf'
},
//注册
filters:{
FormatMyTime(value,str='YYYY年MM月DD日 HH:mm:ss'){
//通过控制台输出:过滤器并没有改变原本的数据, 是产生并返回新的对应的数据
console.log('@',value)
return dayjs(value).format(str)
}
}
})
script>
html>
总结:
Vue内部定义的指令,我们拿来即用
v-bind
:单向绑定解析表达式v-model
:双向数据绑定v-for
:遍历数组、对象、字符串等v-on
:绑定事件监听(简写:@)v-if
v-else
v-else-if
v-show
:条件渲染v-text
:向所在节点渲染文本内容(原有内容直接覆盖)v-html
:向所在节点渲染文本内容(包含html结构)v-once
:所在节点在初次动态渲染后就视为静态内容v-pre
:跳过所在节点的编译过程(初次编译时不需要Vue渲染数据)Vue使用组件三大步骤
定义组件
- 使用
Vue.extend(options)
创建- 注意:
- 创建的组件中不要写
el
,因为所有组件都由Vue实例管理,Vue实例决定使用哪个容器- data必须写成函数 —避免组件被复用时,数据存在引用关系。
- 使用
template
配置组件结构注册组件
局部注册组件,Vue创建实例中注册
new Vue({ components:{ school,//组件名称 student//组件名称 } })
- 1
- 2
- 3
- 4
- 5
- 6
全局注册组件
- 1
- 2
- 3
- 4
使用组件标签
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>几个注意点title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>{{msg}}h1>
<school>school>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//const school = Vue.extend(options) 可简写为:const school = options
//定义组件(方式一)
const s1 = Vue.extend({
//可以使用name配置项指定组件在开发者工具中呈现的名字
name:'School1',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'mtf',
address:'河南'
}
}
})
//定义组件(方式二)
const s2 = ({
name:'School2',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'mtf',
address:'河南'
}
}
})
new Vue({
el:'#root',
data:{
msg:'欢迎学习Vue!'
},
components:{
school:s2
}
})
script>
html>
VueComponent
组件根据上述示例s1、s2
组件本质上是由VueComponent
构造函数来创建的,每次常见组件调用Vue.extend
返回的都是一个全新的VueComponent实例对象 (保证即使使用多次相同的组件,数据变换也不相互影响)
内置关系:VueComponent.prototype.__proto__ === Vue.prototype
让组件实例对象(vc)可以访问到 Vue原型上的属性、方法
ref
和props
<template>
<div>
<h1 ref="title" v-text="msg">h1>
<School ref="sch">School>
<button @click="showDOM()" ref="btn">点击输出DOM元素button>
div>
template>
<script>
import School from "./components/School";
import Student from "./components/Student";
export default {
name: 'App',
components: {Student, School},
data(){
return{
msg:"我是傻子!"
}
},
methods:{
showDOM(){
console.log(this.$refs)
}
}
}
script>
用于父组件给子组件传递数据
App.vue
<template>
<div>
<Student name="mtf" age="22" sex="男">Student>
div>
template>
School.vue
<template>
<div>
<h1>{{msg}}h1>
<h2>学生姓名:{{name}}h2>
<h2>学生性别:{{sex}}h2>
<h2>学生年龄:{{myAge+1}}h2>
<button @click="updateAge">尝试修改收到的年龄button>
div>
template>
<script>
export default {
name:'Student',
data() {
console.log(this)
return {
msg:'我是一个aynu的学生',
myAge:this.age
}
},
methods: {
updateAge(){
this.myAge++
}
},
//简单声明接收
props:['name','age','sex']
//接收的同时对数据进行类型限制
/* props:{
name:String,
age:Number,
sex:String
} */
//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
// props:{
// name:{
// type:String, //name的类型是字符串
// required:true, //name是必要的
// },
// age:{
// type:Number,
// default:99 //默认值
// },
// sex:{
// type:String,
// required:true
// }
// }
}
script>
通过使用模块思想定义一个js文件,给Vue或Vue实例添加方法、定义全局指令
mixin.js
export const hunhe = {
methods: {
showName(){
alert(this.name)
}
},
mounted() {
console.log('你好啊!')
},
}
export const hunhe2 = {
data() {
return {
x:100,
y:200
}
},
}
School.vue
<template>
<div>
<h2 @click="showName">学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
template>
<script>
//引入一个hunhe
import {hunhe,hunhe2} from '../mixin'
export default {
name:'School',
data() {
return {
name:'mtf',
address:'河南',
x:666
}
},
mixins:[hunhe,hunhe2]
}
script>
Vue 插件是一个包含 install 方法的对象 ,通过 install 方法给 Vue 或 Vue 实例添加方法, 定义全局指令等
plugins.js
export default {
install(Vue,x,y,z){
console.log(x,y,z)
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
}
组件之间的通信方式,适用于:子组件===》父组件
父组件给子组件传递函数类型的props来实现子组件给父组件传递数据
App.vue
<template>
<div class="app">
<School :getSchoolName="getSchoolName"/>
div>
template>
<script>
import School from './components/School'
export default {
name:'App',
components:{School},
data() {
return {
msg:'你好啊!'
}
},
methods: {
getSchoolName(name){
console.log('App收到了学校名:',name)
}
}
script>
<style scoped>
.app{
background-color: gray;
padding: 5px;
}
style>
School.vue
<template>
<div class="school">
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
<button @click="sendSchoolName">把学校名给Appbutton>
div>
template>
<script>
export default {
name:'School',
//接收父组件传递过来的函数
props:['getSchoolName'],
data() {
return {
name:'aynu',
address:'安阳',
}
},
methods: {
sendSchoolName(){
//调用父组件传递过来的函数,将子组件数据传递给父组件
this.getSchoolName(this.name)
}
},
}
script>
<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
style>
组件自定义事件
- 通过父组件给子组件绑定一个自定义事件来实现子组件给父组件传递数据
- 解绑自定义事件
- 销毁组件实例==解绑自定义事件(但是回调函数正常运行,只不过函数执行之后的数据不再响应到Vue模板中)
App.vue
<template>
<div class="app">
<h1>{{msg}},学生姓名是:{{studentName}}h1>
<Student @mtf="getStudentName" @demo="m1"/>
<Student ref="student" @click.native="show"/>
div>
template>
<script>
import Student from './components/Student'
export default {
name:'App',
components:{Student},
data() {
return {
msg:'你好啊!',
studentName:''
}
},
methods: {
//当子组件向父组件传递多个数据时,父组件接收多个数据可以使用es6语法接收
getStudentName(name,...params){
console.log('App收到了学生名:',name,params)
this.studentName = name
},
m1(){
console.log('demo事件被触发了!')
},
show(){
alert(123)
}
},
mounted() {
this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)
},
}
script>
<style scoped>
.app{
background-color: gray;
padding: 5px;
}
style>
Student.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}h2>
<h2>学生性别:{{sex}}h2>
<h2>当前求和为:{{number}}h2>
<button @click="add">点我number++button>
<button @click="sendStudentlName">把学生名给Appbutton>
<button @click="unbind">解绑atguigu事件button>
<button @click="death">销毁当前Student组件的实例(vc)button>
div>
template>
<script>
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男',
number:0
}
},
methods: {
add(){
console.log('add回调被调用了')
this.number++
},
sendStudentlName(){
//触发Student组件实例身上的mtf事件
this.$emit('mtf',this.name,666,888,900)
// this.$emit('demo')
// this.$emit('click')
},
unbind(){
this.$off('atguigu') //解绑一个自定义事件
// this.$off(['atguigu','demo']) //解绑多个自定义事件
// this.$off() //解绑所有的自定义事件
},
death(){
this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。
}
},
}
script>
<style lang="less" scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
style>
往子组件插入数据时,子组件只有一个插槽(只有一个
标签),要插入的数据默认插入该位置
//父组件
<template>
<div id="app">
<Category>
Category>
div>
template>
//子组件
<template>
<div>
<solt>solt>
div>
template>
//父组件
<template>
<Category>
<template slot="header">
template>
<template slot="footer">
template>
Category>
template>
//子组件
<template>
<div>
<solt name="header">solt>
<solt name="footer">solt>
div>
template>
适用场景:和默认插槽场景不同,默认插槽要插入的数据在父组件,而作用域插槽适用的场景是父组件要插入的数据需要从带插槽的子组件中获取,这就需要解决子组件的数据怎么传递给父组件!
//父组件
<template>
<div class="container">
<Category title="游戏">
<template scope="mtf">
<ul>
<li v-for="(g,index) in mtf.games" :key="index">{{g}}li>
ul>
template>
Category>
<Category title="游戏">
<template slot-scope="{games}">
<h4 v-for="(g,index) in games" :key="index">{{g}}h4>
template>
Category>
div>
template>
//子组件
<template>
<div class="category">
<h3>{{title}}分类h3>
<slot :games="games" msg="hello">我是默认的一些内容slot>
div>
template>
<script>
export default {
name:'Category',
props:['title'],
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
}
},
}
script>
在了解路由之前,我们先了解一下家里常用的路由器,路由器后面有很多供给我们上网的接口,每天电脑通过链接接口进行上网,因此一个路由器多个接口可以连接多台电脑;这里的一个接口对应一台电脑其实就是一个路由,而路由器负责管理这些路由。其实一个路由就是一组映射关系(key-value)
步骤:
定义路由组件
Home.vue
<template>
<h2>我是Home的内容h2>
template>
<script>
export default {
name:'Home'
}
script>
About.vue
<template>
<h2>我是About的内容h2>
template>
<script>
export default {
name:'About'
}
script>
注册路由
index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About'
import Home from '../components/Home'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
使用路由
App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demoh2>div>
div>
div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<router-link class="list-group-item" active-class="active" to="/about">Aboutrouter-link>
<router-link class="list-group-item" active-class="active" to="/home">Homerouter-link>
div>
div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<router-view>router-view>
div>
div>
div>
div>
div>
template>
<script>
export default {
name:'App',
}
script>
main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由器
import router from './router'
//关闭Vue的生产提示
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router
})
pages
文件夹,一般组件存放在components
文件夹$route
属性,里面存放的是自己的路由信息$router
属性获取router文件夹下的:index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
//name属性,路由命名,通过路由命名可以简化路由跳转了解的编写
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
}
]
}
]
}
]
})
route
对应的query
属性Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
{m.title}} -->
<router-link class="list-group-item" active-class="active" :to="{name:'guanyu'}">Aboutrouter-link>
<router-link :to="{
//二者选一个(路由命名的写法)
name:'xiangqing',
//path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}
router-link>
li>
ul>
<hr>
<router-view>router-view>
div>
template>
<script>
export default {
name:'Message',
data() {
return {
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
}
script>
Detail.vue
<template>
<ul>
<li>消息编号:{{$route.query.id}}li>
<li>消息标题:{{$route.query.title}}li>
ul>
template>
<script>
export default {
name:'Detail',
mounted() {
console.log(this.$route)
},
}
script>
总结:
route
的query
属性传递参数地址栏形式:xxx/?id=001&title=消息001
route
对应的params
属性router文件夹下的:index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
//使用占位符声明接收的params参数
path:'detail/:id/:title',
component:Detail,
}
]
}
]
}
]
})
Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
{m.title}} -->
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
router-link>
li>
ul>
<hr>
<router-view>router-view>
div>
template>
<script>
export default {
name:'Message',
data() {
return {
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
}
script>
Detail.vue
<template>
<ul>
<li>消息编号:{{$route.params.id}}li>
<li>消息标题:{{$route.params.title}}li>
ul>
template>
<script>
export default {
name:'Detail',
mounted() {
// console.log(this.$route)
},
}
script>
注意:
params
属性传递参数,那么跳转路由要是采用to对象写法的话,就只能通过路由命名的name属性值来跳转,不能再通过path的属性值(声明占位符的原因)Vue模板
- 只要数据变化,涉及到该数据的Vue模板就要根据变化的数据重新解析模板
- 因此,页面初始化并不能体会到Vue的特性
两个重要的小原则:
1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
这样this的指向才是vm 或 组件实例对象。