文章目录
一、表单,请求
1.1 表单绑定相关修饰符
-
v-model.lazy
作用是失去焦点,值才会发生改变 -
v-model.number
最终只留下数字 -
v-model.trim
删除两边的空格
<body>
<div id="start">
<input type="text" v-model.lazy="name">{{name}}
<br>
<input type="text" v-model.number="number">{{number}}
<br>
<input type="text" v-model.trim="trim">{{trim}}
<br>
</div>
<script type="text/javascript">
new new Vue({
el:"#start",
data:{
name:"",
number:0,
trim:""
}
})
</script>
</body>
1.2 fetch请求资源
- 本地json文件模拟数据
<body>
<div id="start">
<button @click="handleClick()">获取信息</button>
<ul>
<li v-for="(item,index) in goodslist">{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#start",
data:{
goodslist:[]
},
methods:{
handleClick(){
fetch("test.json").then(res=>{return res.json()}).then(
res=>{
this.goodslist = res.data.list;
}
)
}
}
})
</script>
</body>
-
结果
-
注意
fetch请求默认不带cookie,需要设置 -
请求后端接口
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="../Static/Js/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click="clickhandle()">获取资源</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
vagetable: [
{ name: 'potato',
count:1,
price:3.7 },
{ name: 'tomato',
count:1,
price:3.7 },
{ name: 'onion',
count:1,
price:4.3}
],
price:0,
chooseList:[]
},
methods:{
clickhandle(){
fetch("http://localhost:8081/sendMail",{
method:"POST",
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json'},
body:JSON.stringify({
email:"401129874@qq.com"
})
}).then(res => res.json()).then(res => console.log(res));
}
}
})
</script>
</body>
</html>
- 参考
vue中fetch请求s - fetch请求携带cookie
需要设置参数:
credentials: 'include'
1.3 axios请求资源
- cdn
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
- axios是一个被封装的库
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="../Static/Js/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>
</head>
<body>
<div id="app">
<button @click="clickhandle()">获取资源</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
vagetable: [
{ name: 'potato',
count:1,
price:3.7 },
{ name: 'tomato',
count:1,
price:3.7 },
{ name: 'onion',
count:1,
price:4.3}
],
price:0,
chooseList:[]
},
methods:{
clickhandle(){
axios({
url:'http://localhost:8081/sendMail',
method:"POST",
headers: { 'Content-Type': 'application/json',
},
data:{
email:"401129874@qq.com"
}
}).then(res => console.log(res.data));
}
}
})
</script>
</body>
</html>
- axios的特点
数据外面会被再封装一层data
1.4 vue计算属性
- 和普通方法的比较
如果有多个相同的计算属性,计算属性只会计算一次,而有多个相同的方法时,方法会计算多次。 - 不需要加()
- 计算属性中依赖的值发改变,计算属性会重新计算一次。
<body>
<div id="start">
<p>英文名字首字母大写</p>
<p>计算属性:{{getName}}</p>
<p>普通方法:{{getSth()}}
<script type="text/javascript">
var vm = new Vue({
el:"#start",
data:{
name:"jack",
},
computed:{
getName(){
return this.name.substring(0, 1).toUpperCase() + this.name.substring(1);
}
},
methods:{
getSth(){
return this.name.substring(0, 1).toUpperCase() + this.name.substring(1);
}
}
})
</script>
</body>
1.5 计算属性方式模拟数据过滤
- 可以将计算属性直接写在v-for语句中
<body>
<div id="start">
<input v-model="name">
<ul v-for="(item,index) in getFinalList">
<li>
{{item}}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#start",
data:{
name:"",
list:["aaa","aab","aac","ddd"]
},
computed:{
getFinalList(){
return this.list.filter(res=>{return res.indexOf(this.name) > -1});
}
},
})
</script>
</body>
- 结果
二、组件
2.1 定义全局组件
- 组件作用
封装html元素,扩展可重用的代码
<body>
<div id="start">
<navbar></navbar>
<navbar></navbar>
</div>
<script type="text/javascript">
Vue.component("navbar", {
template:
`<div>
<button @click="handleclick()">返回</button>
<button>主页</button>
</div>`,
methods: {
handleclick(){
console.log("back");
}
}
})
new Vue({
el:"#start"
})
</script>
</body>
- 效果
2.2 定义局部组件
- 局部组件只能父组件使用,其他组件不能使用。
在components属性里面定义
<body>
<div id="start">
<navbar></navbar>
<navbar></navbar>
</div>
<script type="text/javascript">
Vue.component("navbar", {
template:
`<div>
<button @click="handleclick()">返回</button>
<child></child>
<button>主页</button>
</div>`,
methods: {
handleclick(){
console.log("back");
}
},
components: {
child:{
template:`<button @click="childMethod()">子组件</button>`,
methods: {
childMethod(){
console.log("儿子的事件");
}
}
}
}
})
new Vue({
el:"#start"
})
</script>
</body>
2.3 组件和vue实例的区别
- 自定义的组件需要有一个共同的root element
- 父子组件的数据无法共享
- 组件的data属性必须是一个函数
Vue.component("navbar", {
template:
`<div>
<button @click="handleclick()">返回</button>
{{father}}
<button>主页</button>
</div>`,
methods: {
handleclick(){
console.log("back");
}
},
data () {
return {
father:"father 的数据"
}
},
})
2.4 父子组件
- 父子组件之间的data,method不能相互使用
- data必须是一个函数
- 组件在div中使用,则div是他的父组件
- 组件和他的局部组件之间也是父子关系
2.5 组件中的父传子
- 简单的说就是修改组件的一部分属性,让组件在不同的场合显示不同的内容
<body>
<div id="start">
<navbar :mytitle="title" :show="true"></navbar>
<navbar :mytitle="title1" :show="false"></navbar>
</div>
<script type="text/javascript">
Vue.component("navbar", {
template:
`<div>
<button @click="handleclick()">返回</button>
{{mytitle}}
<button v-show="show">主页</button>
</div>`,
methods: {
handleclick(){
console.log("back");
}
},
props: ["mytitle","show"]
})
new Vue({
el:"#start",
data:{
title:"呵呵",
title1:"嘿嘿"
}
})
</script>
</body>
- 效果
注意:使用v-bind来动态绑定外面传入的值,即不把此处的值当做普通的字符串来处理。
2.6 属性验证
- 父传子时验证父组件传过来的值类型
- 记得要使用:进行绑定
props: {
mytitle:String,
show:Boolean
}
2.7 子传父
- 把子组件的状态传递给父组件
通过在子组件的事件中,调用$emit
(“父组件方法名”,传递的参数)方法实现,父组件接收参数的方式:method或者method($event
)来接收参数 - method(
$event
)中的$event
是固定写法,不然得不到参数
<body>
<div id="start">
<son @event1="fatherGet($event)"></son>
<p>得到的子组件的状态:{{sonStatue}}</p>
</div>
<script type="text/javascript">
Vue.component("son", {
template: `
<div>
<button @click="sonShow()">按钮</button>
<p>子组件的状态:{{statue}}</p>
</div>`,
methods: {
sonShow() {
this.$emit("event1",this.statue);
console.log("点击了");
}
},
data() {
return {
statue: "alive"
}
},
})
new Vue({
el: "#start",
data:{
sonStatue:""
},
methods:{
fatherGet(ev){
this.sonStatue = ev;
console.log("父组件得到的子组件的状态值:" + ev);
}
}
})
</script>
</body>
2.8 子传父案例
- 有两个组件,点击组件2的按钮控制组件1的隐藏与显示。
2.9 ref通信
- ref放在节点上,拿到的是原生节点
<body>
<div id="start">
<input type="text" ref="myref" @input="myInput">{{text}}
</div>
<script type="text/javascript">
new Vue({
el:"#start",
data:{
text:""
},
methods: {
myInput(){
this.text = this.$refs.myref.value;
console.log(this.$refs.myref.value);
}
}
})
</script>
</body>
- ref放在组件上,拿到的是组件对象
2.10 ref通信模拟父传子
- 给子组件传递数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="../Static/Js/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>
</head>
<body>
<div id="app">
<navbar ref="child"></navbar>
<button @click="dosth()">点击</button>
</div>
<script>
Vue.component("navbar",{
template:`
<div>
<button>组件二</button>
</div>`,
methods: {
getSth(data){
console.log("触发了事件" + "父组件传过来的数据" + data)
}
},
data () {
return {
str:"子组件的数据"
}
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
dosth(){
console.log(this.$refs.child.str);
this.$refs.child.getSth("ahaha");
}
}
})
</script>
</body>
</html>
- 通过ref很容易实现子传父和父传子,但是不推荐使用,因为要定义大量的ref
三、非父子通信
3.1 中央事件总线
- 中央事件总线作为一个中间人的角色,发布者把要通信的内容发布到中央事件总线上,订阅者去该事件总线上订阅即可
<body>
<div id="start">
<brother1></brother1>
<brother2></brother2>
</div>
<script type="text/javascript">
var bus = new Vue();
Vue.component("brother1",
{
template:
`<div>
<input ref="myInput">
<button @click="myclick()">按钮</button>
</div>`,
methods: {
myclick(){
bus.$emit("wxMsg",this.$refs.myInput.value);
console.log("发布了"+this.$refs.myInput.value);
}
}
}),
Vue.component("brother2",
{
template:
`<p>得到了订阅的消息:{{value}}</p>`,
methods: {
},
mounted () {
bus.$on("wxMsg",(data)=>{
this.value = data;
console.log("收到了消息" + data);
})
},
data () {
return {
value:""
}
}
})
new Vue({
el:"#start",
data:{
},
methods:{
}
})
</script>
</body>
- 结果
- mounted
初始化dom对象时就会触发里面的内容。
- 组件名不能大写
2.6 动态组件
- 将多个组件的值绑定到is属性上
<body>
<div id="start">
<component :is="who"></component>
<footer>
<ul>
<button @click="who='start'">首页</button>
<button @click="who='shop'">购物</button>
<button @click="who='mine'">我的</button>
</ul>
</footer>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#start",
data:{
who:""
},
methods:{
},
components: {
"start":{
template:`<p>这是首页</p>`
},
"mine":{
template:`<p>这是我的页面</p>`
},
"shop":{
template:`<p>这是购物页面</p>`
},
}
})
</script>
</body>
- keep-aclive标签
使切换组件时,保持上一个组件的状态
<keep-alive>
<component :is="who"></component>
</keep-alive>
2.7 slot插槽
- 作用
插槽的作用是使在组件之间新增的标签生效
components: {
"start":{
template:`
<div>
<slot></slot>
<p>这是首页</p>
<input type="text">
</div>`
},
}
- 也可以通过插槽访问到父组件的作用域
可以很简单的实现一个组件控制另一个组件的隐藏与显示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="../Static/Js/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>
</head>
<body>
<div id="app">
<navbar><button @click="show = !show">控制</button></navbar>
<sidebar v-show="show"></sidebar>
</div>
<script>
Vue.component("navbar",{
template:
`
<div>
<slot></slot></div>`
})
Vue.component("sidebar",{
template:
`<div>这是sidebar
</div>`
})
var vm = new Vue({
el:"#app",
data:{
show:true,
}
})
</script>
</body>
</html>
2.8 具名插槽
- 通过标签中的slot
<p slot="b">
属性指定要插入的插槽的名称 - 通过
<slot name="b"></slot>
指定插槽的名称
div id="start">
<start><p slot="a">aaaaaaa</p>
<p slot="b">bbbbbbb</p></start>
</div>
<body>
<body>
<div id="start">
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#start",
data:{
},
methods:{
},
components: {
"start":{
template:`
<div>
<slot name="a"></slot>
<p>这是首页</p>
<slot name="b"></slot>
<input type="text">
</div>`
},
}
})
</script>
</body>