回过头,把vue的知识点梳理一遍.?
组件
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="root">
<table>
<tbody>
<myrow></myrow>
<myrow></myrow>
<myrow></myrow>
</tbody>
/* 初学者都容易这样写:
认为在vue全局申明组件之后,直接在标签内写上申明的组件名即可.
这里虽然可以成功渲染.但是渲染出来的层级是不对的.
我们会发现这样一种层级:
tbody
myrow
myrow
myrow
tbody
很明显,我们希望将myrow显示在tbody内部:
但基于h5语法,在tbody下需要存放的应该是tr,
然而我们想要显示的确是自己的myrow组件.
于是高潮来了:
*/
<tbody>
<tr is="myrow"></tr>
<tr is="myrow"></tr>
<tr is="myrow"></tr>
</tbody>
/*我们在tbody下写上tr,再在tr上添加vue的is属性,他的意思是,
虽然这里是tr标签,但我们真正需要渲染出来的是 "myrow"组件.
此时就都解决了
*/
/*
一定要注意的是: 这个bug是出自于h5,比如 :
ul 下的标签最希望的li,
select 下的 最希望是 option等
所以玩组件,一定要回头看层级,谨记!
出了bug , 请使用is属性解决
*/
</table>
</div>
</body>
Vue.component("myrow",{
template:"<tr><td>this is a row</td></tr>"
})
var vm = new Vue({
el:"#root"
})
ref 与 refs
虽然vue不推荐操作dom,但在某些时候,比如针对"动画"需求的时候,
仅仅操作数据就显得力不从心了,我们在vue中,使用ref 和 refs的组合操作dom
<div ref="hello" @click="handleclick()"> hello world</div>
var vm = new Vue({
el:"#root",
methods:{
handleclick:function(){
alert(this.$refs.hello.innerHTML);
//在这里如此操作即可成功操作dom
}
}
})
注意
ref 配合着 refs 写在标签上的时候,获取到的是这个标签的dom元素
而写在组件上的时候,代表的是引用
Demo 写一个累加器
<div id="root">
<com ref="one" @change='totaladd()'></com>
<com ref="two" @change='totaladd()'></com>
<div>{{total}}</div>
</div>
Vue.component("com",{
template:"<div @click='handleClick()'> {{num}} </div>",
data(){
return {
num:0
}
},
methods:{
handleClick(){
this.num++;
this.$emit("change");
}
}
})
var vm = new Vue({
el:"#root",
data(){
return{
total:0
}
},
methods:{
totaladd(){
this.total = this.$refs.one.num+this.$refs.two.num
}
}
})
父组件与子组件之间的信息传递:
父组件通过 属性(加冒号)的形式向子组件传递信息,子组件使用props接收
<div id="root">
//如果拿属性传递,那么传递的将是 number类型的1
// 直接传递,传递的将是字符串类型的 1
<counter :count="1"></counter>
<counter :count="2"></counter>
</div>
注意:
vue中单项数据流 : 多个子组件使用一个父组件的传递的数据,为了防止某个子组件修改数据,导致所有子组件数据紊乱,
所以不可以违背单项数据流,如果想修改某个数据,可以在子组件上定义一个变量,将传递来的数据给该变量赋值,
再去修改该变量即可.
否则报 "warn警告"
var counter = {
// 接受传递后 使用props 接收值
props:["count"],
//插值表达式 渲染
template:"<div @click='handelClick()'>{{count}}</div>",
//为了遵循单项数据流 而定义的对象
data(count){
return {
num :this.count
}
},
methods:{
handelClick(){
num++
}
}
}
var vm = new Vue({
el:"#root",
//申明,组件注册
components:{
counter:counter
}
})
子组件向父组件传值 : 通过事件传值
this.$emit.("事件名称")
$emit 可以接受多个参数,首个参数是事件名,后面的会被作为 参数 传递给监听的函数
<div @inc="handle"></div> //被emit监听触发后,会执行 handle函数
this.$emit.("inc",5); //给div写监听 这个inc是个可随便写的,并不仅拘泥于 inc
handle(step){
console.log(step); //5 step 是emit的第二个参数
}
//这就代表着
组件数据传递校验
//html
<child content="abcdef"></child>
Vue.component('child',{
// props:['content'], 此时content是一个字符串
// 如果我们想对传递来的数据进行约束(参数校验) 可以这样写
// props:{
// content:[String,Number,Object]
// },
//如果上述 写成<child :content="123"></child>
//那么 vue会报一个warn 因为加上冒号 传递来的是一个 number类型
//如果 <child content="123"></child> 就没有问题 ,因为传递来的是一个字符串了
//写成 props:{content:[String,Number]} 表示传递来的数据既可以是数字,也可以是字符串
//另一种写法:
props:{
content:{
type:String, //表示传递来的数据是对象类型
required:false, //且 必须传递 不传递会报错
default:"{a:4}", //设置默认值,即便有了默认值,不传递的情况下,也会报错
validator:function(content){ //判断传递过来的数据 长度等具体属性
return (content.length >2) //校验失败 则报错
}
}
},
template:'<div>{{content}}</div>',
data(){
return{
message:0
}
}
})
var vm = new Vue({
el:"#root"
})
为组件绑定原生事件
在之前我们希望直接让组件触发事件,需要使用$emit.("事件名").
经过两层迂回才可以触发,实际上并不需要这样麻烦,直接在最外层的@click后面添加.native即可
<mycomponent @click.native="hancleClick()"></mycomponent >
非父子组件之间的数据传递(Bus/总线/发布订阅模式/观察者模式)
//html
<div id="root">
<child content="Juno"></child>
<child content="Mak"></child>
</div>
//js
Vue.prototype.bus = new Vue();
Vue.component("child",{
//定义一个mycontent 为了遵守单项数据流
data(){
return {
mycontent:this.content
}
},
//数据校验
props:{
content:{
type:String
}
},
template:"<div @click='handleClick'>{{mycontent}}</div>",
methods:{
handleClick:function(){
// 使用bus向外部触发事件 $emit(change),并传递mycontent
this.bus.$emit("change",this.mycontent);
}
},
//挂载
mounted:function(){
var _this = this;
// 使用bus进行监听 bus是vue的实列,也有on方法
this.bus.$on("change",function(msg){
_this.mycontent = msg
})
}
})
var vm = new Vue({
el:"#root"
})
插槽 slot
//html
<div id="root">
<child>
<!--1. 我们首先在定义的子组件内部写上想要渲染的数据 -->
<p>dell</p>
</child>
</div>
//js
Vue.component("child",{
//2.然后在template中写上<slot></slot>即可
// 注意: 插槽支持添加默认值,如果子组件内部没有添加任何内容,那么插槽才会显示默认内容
//否则不显示默认内容
template:`<div><slot>我是插槽默认值</slot></div>`
})
var vm = new Vue({
el:"#root"
})
新需求 :如果有两个插槽,如何让他们有顺序地摆放呢?
具名插槽!
//html
<div id="root">
<child>
<!--1. 我们首先在具名插槽上规定slot="???" 具体的名字 -->
<div slot="headerslot">1</div>
<div slot="footerslot">2</div>
<p>dell</p>
</child>
</div>
//js
Vue.component("child",{
//2.然后在slot中写上对应的name即可
template:`<div><slot name="headerslot">我是插槽默认值</slot>
<div>content</div>
<slot name="footerslot">我是插槽默认值</slot></div>`
})
var vm = new Vue({
el:"#root"
})
注意: 无论是插槽还是具名插槽,都可以含有默认值;触发的时机是在组件中未定义的时候. 插槽默认值还支持标签(h5语法都可以:类名\id\内联css)
作用域插槽
slot
动态组件
v-once
方法只执行一次
axios
axios 已经 取代vue-resource,成为vue全家桶中官方的请求插件。
axios get方法
get方法的请求体 一定需要用params包裹 谨记!
axios.get("www.123.com/getId",{
params:{
userId: "4536",
Islike: "1",
count: "15"
},
headers: {
token: "2hu9Xw9d_Dh29doFWs8__82nndn7cq234d8Ete2t75G458D5f44"
}
}).then(function(res){
console.log(res)
}).catch(function(err){
console.log(err)
})
axios post方法
post方法有三个参数:
第一个参数:“请求的域名" --- str
第二个参数:"请求体" --- obj
第三个参数:"请求头" --- obj
axios.post("www.123.com/getId",{
userID: "888"
},{
headers: {
token: "Tom"
}
}).then(function(res){...}).catch(function(err){...})
http请求
axios({
url: "www.123.com/userid",
methods: "get",
data: {userID: "001"},
headers:{token:"2hu9Xw9d_Dh29doFWs8__82nndn7cq234d8Ete2t75G458D5f44"}
}).then(res=>{}).catch(err=>{})
axios的拦截器
下面的代码优先会打印 request init,
再执行后续操作
axios.interceptors.request.use(function(config){
console.log("request init.");
return config;
})