vue day(2) 表单,请求,组件,父子通信

一、表单,请求

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>

需要设置参数:

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的隐藏与显示。
Vue 测试实例 - 菜鸟教程(runoob.com)
``` Vue 测试实例 - 菜鸟教程(runoob.com)
```

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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值