1vue.js安装(3种方式)
1.1下载和引入(vue官网:https://cn.vuejs.org/v2/guide/installation.html)
开发环境 https://vuejs.org/js/vue.js
生产环境 https://vuejs.org/js/vue.min.js
1.1.1安装步骤
1.1.1.1官网下载vue.js,右键链接另存为。
1.1.1.2idea新建工程,打开idea ->Create New Projec->Empty Project。
1.1.1.3新建module。
1.1.1.4选中static web,静态web项目。
1.1.1.5项目右键,新建js文件夹,NEW->Directory,把下载的vue.js文件放到该目录下。
1.1.1.6新建src文件夹,NEW->HTML文件。
1.2直接CDN引入
或者也可以直接使用公共的CDN服务:<!-- 开发环境版本,包含了用帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或者:<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
1.3npm安装
详细参考:https://www.cnblogs.com/konglxblog/p/14489251.html
2vue语法
2.1vue生命周期
请参照官网的生命周期图示。
<div>{{name}}</div>
- beforeCreated:我们在用Vue时都要进行实例化,因此,该函数就是在Vue实例化时调用,也可以将他理解为初始化函数比较方便一点,在Vue1.0时,这个函数的名字就是init。
- created:在创建实例之后进行调用。
- beforeMount:页面加载完成,没有渲染。如:此时页面还是{{name}}
- mounted:我们可以将他理解为原生js中的window.οnlοad=function({.,.}),可以理解为jquery中的$(document).ready(function(){….}),他的功能就是:在dom文档渲染完毕之后将要执行的函数,该函数在Vue1.0版本中名字为compiled。 此时页面中的{{name}}已被渲染成相对应的name的值。
- beforeDestroy:该函数将在销毁实例前进行调用 。
- destroyed:改函数将在销毁实例时进行调用。
- beforeUpdate:组件更新之前。
- updated:组件更新之后。
2.2vue实例
var vm = new Vue({ // 选项 })
2.3插值(6种插值方式以及对比)
Mustache:双大括号:{{val}}
v-once
- 在某些情况下,我们可能不希望界面随意的跟随改变,这个时候,我们就可以使用一个Vue命令
- 该指令后面不需要跟任何表达式(比如v-for后面是有跟表达式的)
- 该指令表示元素和组件(组件后面会写)只渲染一次,不会随着数据的改变而改变。
v-html
- 如果我们直接通过{{}}来输出,会将HTML代码也一起输出,但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
- 如果我们希望解析出HTML展示
- 可以使用
v-html
指令,在该指令后面往往会跟上一个string
类型,会将string
的html
解析出来并且进行渲染
v-text
- v-text作用和Mustache比较相似,都是用于数据显示在界面中,v-text通常情况下,接受一个
string
类型
v-pre
- v-pre用于跳过这个元素和它之元素的编译过程,用于显示原本的Mustache语法,比如下面的代码:
- 第一个h1元素中的内容会被编译解析出来
- 第二个h1元素中会直接显示{{message}}
v-cloak
- 在某些情况下, 我们浏览器可能会直接显示出未编译的Mustache标签(解决vue语法会有延迟加载显现{{xxx}}的问题)。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="hello">
<p id="mustache" >{{message}}</p>
<p id="text" v-text="message"></p>
<p id="once" v-once="message"></p>
<p id="html" v-html="message"></p>
<p id="pre" v-pre="message"></p>
<p id="cloak" v-cloak="message"></p>
<p id="p1" >====================================</p>
<p id="text1" v-text="message">text</p>
<p id="once1" v-once="message">once</p>
<p id="html1" v-html="message">html</p>
<p id="pre1" v-pre="message">pre</p>
<p id="cloak1" v-cloak="message">cloak</p>
<p id="p2" >p2</p>
<p id="mustache-v">{{message}}</p>
<p id="v-pre" v-pre>{{message}}</p>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var vm = new Vue({
el:"#hello",
data:{
message:"<div id='msg'>hello my name is vue</div>"
}
});
</script>
</html>
运行结果:
修改message的值
2.4指令
2.4.1插值表达式,花括号
格式:{{表达式}}。
-
该表达式支持JS语法,可以调用js内置函数(必须有返回值)。
-
表达式必须有返回结果。例如 1 + 1,没有结果的表达式不允许使用,如:var a = 1 + 1。
-
可以直接获取Vue实例中定义的数据或函数。
我们将网速调慢一些,测试插值闪烁方法:
-
该表达式支持JS语法,可以调用js内置函数(必须有返回值)。
-
表达式必须有返回结果。例如 1 + 1,没有结果的表达式不允许使用,如:var a = 1 + 1。
-
可以直接获取Vue实例中定义的数据或函数。
我们将网速调慢一些,测试插值闪烁方法:
然后刷新页面。
2.4.2
说明:
-
v-text:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出。
-
v-html:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染。
2.4.3v-model
双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。目前v-model的可使用元素有:
-
input
-
select
-
textarea
-
checkbox
-
radio
-
components(Vue中的自定义组件)
基本上除了最后一项,其它都是表单的输入项。
-
-
radio对应的值是input的value值
-
text
和textarea
默认对应的model是字符串 -
select
单选对应字符串,多选对应也是数组
2.4.4v-on
v-on指令用于给页面元素绑定事件。
语法:
v-on:事件名="js语句或函数名"。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div >计数器,当前基数:{{count}}</div>
<!-- <button v-on:click="count++">加加</button>
<button v-on:click="count++">减减</button>-->
<!-- <button v-on:click="add">加加</button>
<button v-on:click="minus">减减</button>-->
<button @click="add">加加</button>
<button @click="minus">减减</button>
</div>
</body>
<script src="../../js/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
count:1
},methods:{
add(){
this.count++
},
minus(){
this.count--
}
}
});
</script>
</html>
2.4.5事件修饰符和按键修饰符
为了解决这个问题,Vue.js 为 v-on
提供了事件修饰符。修饰符是由点开头的指令后缀来表示的。
-
stop
:阻止事件冒泡到父元素 -
prevent
:阻止默认事件发生 -
capture
:使用事件捕获模式 -
self
:只有元素自身触发事件才执行。(冒泡或捕获的都不执行) -
once
:只执行一次
代码示例:效果:(右键“增加一个”,不会触发默认的浏览器右击事件;右键“减少一个”,会触发默认的浏览器右击事件)
<div id="app">
<!--右击事件,并阻止默认事件发生-->
<button v-on:contextmenu.prevent="num++">增加一个</button>
<br/>
<!--右击事件,不阻止默认事件发生-->
<button v-on:contextmenu="decrement($event)">减少一个</button>
<br/>
<h1>{{num}}</h1>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
num: 100
},
methods: {
decrement(ev) {
// ev.preventDefault();
this.num--;
}
}
})
</script>
按键修饰符
- enter*
- tab
- delete (捕获“删除”和“退格”键)
- esc
- space
- up
- down
- left
- right
用法例子:
<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">
组合按钮
- .ctrl
- .alt
- .shift
例如:
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
2.4.6v-for
遍历数组
语法:v-for="item in items"
-
-
item:迭代得到的数组元素的别名
示例
<div id="app">
<ul>
<li v-for="user in users">
{{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
users:[
{name:'娜美', gender:'女', age: 21},
{name:'路飞', gender:'男', age: 18},
{name:'陆琪', gender:'女', age: 24},
{name:'名人', gender:'女', age: 18},
{name:'鸣人', gender:'女', age: 25}
]
},
})
</script>
-
-
item:迭代得到的数组元素别名
-
index:迭代到的当前元素索引,从0开始。
示例
<ul>
<li v-for="(user, index) in users">
{{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
v-for除了可以迭代数组,也可以迭代对象。语法基本类似
语法
- v-for="value in object"
- v-for="(value,key) in object"
- v-for="(value,key,index) in object"
示例
<div id="app">
<ul>
<li v-for="(value, key, index) in user">
{{index + 1}}. {{key}} - {{value}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
user:{name:'佐助', gender:'男', age: 18}
}
})
</script>
当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
这个功能可以有效的提高渲染的效率。
但是要实现这个功能,你需要给Vue一些提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
属性。理想的 key
值是每项都有的且唯一的 id。
示例:
<ul>
<li v-for="(item,index) in items" :key=index></li>
</ul>
-
这里使用了一个特殊语法:
:key=""
,它可以让你读取vue中的属性,并赋值给key属性 -
这里我们绑定的key是数组的索引,应该是唯一的
2.4.8
v-if,顾名思义,条件判断。当得到结果为true时,所在的元素才会被渲染。
语法:
v-if="布尔表达式"
示例
<div id="app">
<button v-on:click="show = !show">show me</button>
<br>
<h1 v-if="show">
show me
</h1>
<h1 v-show="show">
show me
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
show: true
}
})
</script>
当v-if和v-for出现在一起时,v-for优先级更高。也就是说,会先遍历,再判断条件。
修改v-for中的案例,添加v-if:
<ul>
<li v-for="(user, index) in users" v-if="user.gender == '女'">
{{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
<div id="app">
<h1 v-if="Math.random() > 0.5">
看到我啦?!if
</h1>
<h1 v-else>
看到我啦?!else
</h1>
</div>
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别。
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用:
<div id="app">
<button v-on:click="random=Math.random()">点我呀</button><span>{{random}}</span>
<h1 v-if="random >= 0.75">
看到我啦?!if
</h1>
<h1 v-else-if="random > 0.5">
看到我啦?!if 0.5
</h1>
<h1 v-else-if="random > 0.25">
看到我啦?!if 0.25
</h1>
<h1 v-else>
看到我啦?!else
</h1>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
random: 1
}
})
</script>
<h1 v-show="ok">Hello!</h1>
<div id="app">
<!--事件中直接写js片段-->
<button v-on:click="show = !show">点击切换</button><br/>
<h1 v-if="show">
你好
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
show:true
}
})
</script>
2.4.9
html属性不能使用双大括号形式绑定,只能使用v-bind指令。
在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
<div id="app">
<!--可以是数据模型,可以是具有返回值的js代码块或者函数-->
<div v-bind:title="title" style="border: 1px solid red; width: 50px; height: 50px;"></div>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
title: "title",
}
})
</script>
<div id="app">
<div v-bind:class="activeClass"></div>
<div v-bind:class="errorClass"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
activeClass: 'active',
errorClass: ['text-danger', 'text-error']
}
})
</script>
对象语法
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示 active
这个 class 存在与否将取决于数据属性 isActive
的truthiness(所有的值都是真实的,除了false,0,“”,null,undefined和NaN)。
你可以在对象中传入更多属性来动态切换多个 class。此外,v-bind:class
指令也可以与普通的 class 属性共存。如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
和如下 data:
data: {
isActive: true,
hasError: false
}
渲染结果为
<div class="static active"></div>
active样式和text-danger样式的存在与否,取决于isActive和hasError的值。本例中isActive为true,hasError为false,所以active样式存在,text-danger不存在。
绑定style样式
数组语法
数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
数据
data: {
baseStyles: {'background-color': 'red'},
overridingStyles: {border: '1px solid black'}
}
渲染后结果
<div style=" border: 1px solid black;"></div>
对象语法
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
数据
data: {
activeColor: 'red',
fontSize: 30
}
效果
<div style="color: red; font-size: 30px;"></div>
简写
在插值表达式中使用js表达式是非常方便的,而且也经常被用到。
但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便,例如下面的场景,我们有一个日期的数据,但是是毫秒值:
data:{
birthday:1529032123201 // 毫秒值
}
我们在页面渲染,希望得到yyyy-MM-dd的样式:
<h1>您的生日是:{{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
</h1>
虽然能得到结果,但是非常麻烦。
Vue中提供了计算属性,来替代复杂的表达式:
var vm = new Vue({
el:"#app",
data:{
birthday:1429032123201 // 毫秒值
},
computed:{
birth(){// 计算属性本质是一个方法,但是必须返回结果
const d = new Date(this.birthday);
return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay();
}
}
})
计算属性本质就是方法,但是一定要返回数据。然后页面渲染时,可以把这个方法当成一个变量来使用。
页面使用:
<div id="app">
<h1>您的生日是:{{birth}} </h1>
</div>
2.6
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<div id="watch">
<input type="text" v-model="message">
</div>
</body>
<script src="../../js/vue.js"></script>
<script>
var vm = new Vue({
el:"#watch",
data:{
message:"wacth"
},
watch:{
message(newVal, oldVal){
console.log(newVal, oldVal);
}
}
});
</script>
</html>
例子:在页面上的text框里分别输入1,2,3,4,5,6。可以看到控制台的变化,监控输入框的新值和旧值。
3组件
组件的使用分成三个步骤:
- 创建组件构造器
- 注册组件
- 使用组件。
3.1定义全局组件的方式。
3.1.1方法1,使用extend
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--3.使用组件-->
<my-tem></my-tem>
<my-tem></my-tem>
<div>
<div id="tem">
<my-tem></my-tem>
</div>
</div>
</div>
<my-tem></my-tem>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器对象
const temC = Vue.extend({
template: `
<div>
<h2>组件</h2>
<p>组件内容</p>
</div>`
})
// 2.注册组件
Vue.component('my-tem', temC)
const app = new Vue({
el: '#app',
data: {
message: '组件内容'
}
})
</script>
</body>
</html>
3.1.2方法2,使用字符串形式
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
template:'<button v-on:click="count++">你点了{{ count }} 次.</button>',
data(){
return {
count:0
}
}
})
var app = new Vue({
el:"#app"
})
</script>
3.1.3方法3,模版字面量
Vue.component("my-content", {
data: function () {
return {
label: "组件",
content: "组件内容"
}
},
template: `
<div>
<button>{{ label }}</button>
<span>{{ content }}</span>
</div>
`
});
3.1.4方法4,内联模版(inline-template)
<my-label inline-template>
<span>{{label}}</span>
</my-label>
Vue.component('my-label', {
data: function () {
return {
label: "hello"
}
}
})
3.1.5方法5,X-template
定义一个 <script> 标签,标记 text/x-template
类型,通过 id 链接。
<script type="text/x-template" id="label-template">
<span>{{label}}</span>
</script>
Vue.component('my-label', {
template: "#label-template",
data: function () {
return {
label: "test"
}
}
})
3.1.6方法6,template
//tem.vue
<template>
<div>
<h1>我是标题一</h1>
</div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
3.1.7方法7,渲染函数创建节点方式(实现效果和方法6一模一样)
//ren.vue
<script>
export default {
render: function(createElement) {
return createElement('h1', '我是标题一')
}
}
</script>
render总共接收三个参数,第一个参数为标签名
('ul'
),第二个参数为数据对象
,第三个参数为子节点
(我是标题一
),要么文本
要么是存储着一个或一个以上的子节点数组.
render 函数创建多个子节点
实现下面的效果:
- li-1
- li-2
- li-3
代码如下:
<script>
export default {
render: function(createElement) {
return createElement('ul', [
createElement('li', 'li-1'),
createElement('li', 'li-2'),
createElement('li', 'li-3')
])
}
}
</script>
简化后:
<script>
export default {
data() {
return {
list: ['li-1', 'li-2', 'li-3']
}
},
render: function(createElement) {
return createElement(
'ul',
this.list.map(_ => {
return createElement('li', _)
})
)
}
}
</script>
3.1.8方法8,函数渲染返回xml结构方式。
Vue.component('my-label', {
data: function () {
return {
label: ["活动结束"]
}
},
render(){
return <div>{this.label}</div>
}
})
3.2全局组件
我们通过Vue的component方法来定义一个全局组件。
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
</div>
<script src="./vue.js"></script>
<script type="text/javascript">
// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
template:'<button v-on:click="count++">你点了{{ count }} 次.</button>',
data(){
return {
count:0
}
}
})
var app = new Vue({
el:"#app"
})
</script>
-
-
不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
-
但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
-
全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
-
data必须是一个函数,不再是一个对象。
3.3局部组件
因此,对于一些并不频繁使用的组件,我们会采用局部注册。
我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:
const counter = {
template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
data(){
return {
count:0
}
}
};
然后在Vue中使用它:
var app = new Vue({
el:"#app",
components:{
counter:counter // 将定义的对象注册为组件
}
})
-
-
其key就是子组件名称
-
其值就是组件对象名
-
-
效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用
3.4组件通信
-
-
子组件通过props接收父组件数据,通过自定义属性的属性名
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<child_temp v-bind:child_msg="parent_msg" :chlid_movies="parent_movies"></child_temp>
</div>
<template id="child_temp">
<div>
<ul>
<li v-for="item in chlid_movies">{{item}}</li>
</ul>
<p>{{child_msg}}</p>
<p>{{chlid_movies}}</p>
<p>{{myname}}</p>
<!--<button @click="child_btn">子按钮</button>-->
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
const child_temp = {
template:'#child_temp',
/*props:['chlid_movies','child_msg'],*/
props:{
//props的扩展,包括类型,默认值,是否必须等
//1类型限制
/*chlid_movies:Array,
child_msg:String*/
//2.提供默认值,扩展
chlid_movies:{
type:Array,
default() {
return [];
}
},
child_msg: {
type: String,
required: true,
default() {
//如果把child_temp模板里的v-bind:child_msg="parent_msg"去掉,页面就会显示这里的值
return ["子_我是子组件默认值,当使用父组件data里的属性值得时候,如果没有用v-bind绑定,会取到我这一串值"];
}
}/*,
methods:{
child_btn(){
alert("我是子组件的方法")
}
}*/
},
data(){
return {
myname:"子_我是子属性自己的值,我使用的是自己组件里的data的属性值"
}
}
}
var vm = new Vue({
el:"#app",
data:{
parent_msg:"父_我是父组件里的信息,传到了子组件",
parent_movies:['父_火影','父_海贼王','父_柯南']
},
components:{
child_temp
}
})
</script>
</html>
效果:
-
items:是要接收的属性名称
- type:限定父组件传递来的必须是数组
- default:默认值
- required:是否必须
验证支持的数据类型
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
<temp child_msg="大家好,我是组件"/>
给 prop 传入一个动态的值: (通过v-bind从数据模型中,获取title的值)
<temp :child_msg="parent_msg"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父组件模板-->
<div id="app">
<!--监听子组件发射出的btn_child_click事件,find_parent_click要在父组件里定义methods-->
<chlid_temp v-on:btn_child_click="find_parent_click"></chlid_temp>
</div>
<!--子组件模板-->
<template id="chlid_temp">
<div>
<button v-for="item in movies"
@click="btn_ckik(item)">
{{item.id}}-{{item.name}}
</button>
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
//子组件
const chlid_temp = {
template:"#chlid_temp",
data(){
return{
movies:[
{id:"1",name:"火影"},
{id:"2",name:"海贼"},
{id:"3",name:"七大罪"},
{id:"4",name:"菜鸟java是怎么炼成的"},
{id:"5",name:"菜鸟是怎么变菜的"},
]
}
},
methods:{
btn_ckik(ev){
//自定义事件
this.$emit("btn_child_click",ev)
}
}
}
//父组件
var vm = new Vue({
el:"#app",
data:{
msg:"我是父组件的信息-msg"
},
components:{
chlid_temp
},
methods:{
find_parent_click(ev){
console.log(ev)
console.log(ev.id +" "+ev.name)
}
}
});
</script>
</html>
3.5父子通信示例:
需求:父组件里的num1和num2,和子组件里的num1和num2实现双向绑定,并且input1里的num1输入后input2里num2的值会相应的变为num1值得100倍,反之num2是num1的100分之1.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<temp :c_num1="p_num1"
:c_num2="p_num2"
@data_cnum1_change="parent_cnum1_change"
@data_cnum2_change="parent_cnum2_change"
></temp>
</div>
<template id="temp">
<div>
<h3>props:{{c_num1}}</h3>
<h3>data:{{data_cnum1}}</h3>
<!--<input type="text" v-model="data_cnum1">-->
input1:<input type="text" :value="data_cnum1" @input="num1_input">
<h3>props:{{c_num2}}</h3>
<h3>data:{{data_cnum2}}</h3>
<!--<input type="text" v-model="data_cnum2">-->
<!--<input type="text" :value="data_cnum2" @input="data_cnum2=$event.target.value">-->
input2:<input type="text" :value="data_cnum2" @input="num2_input">
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
const temp={
template:"#temp",
props:{
c_num1:Number,
c_num2:Number
},
data(){
return{
data_cnum1:this.c_num1,
data_cnum2:this.c_num2
}
},
methods:{
num1_input(e){
//1 将input的value赋值到data_cnum1上
this.data_cnum1 = e.target.value;
//2 为了让父组件可以改值,发出一个事件
this.$emit("data_cnum1_change",this.data_cnum1);
//3 同事修改data_cnum2的值(data_cnum2的值是data_cnum1的100倍)
this.data_cnum2 = this.data_cnum1 * 100;
this.$emit("data_cnum2_change",this.data_cnum2)
},
num2_input(e){
this.data_cnum2 = e.target.value;
this.$emit("data_cnum2_change",this.data_cnum2);
//(data_cnum2的值是data_cnum1的100分之一倍)
this.data_cnum1 = this.data_cnum2 / 100;
this.$emit("data_cnum1_change",this.data_cnum1)
}
}
}
var vm = new Vue({
el:"#app",
data:{
p_num1:1,
p_num2:0
},
components:{
temp
},
methods:{
parent_cnum1_change(data_cnum1){
//默认传过来的是Strnig类型,需要转换成number
console.log(typeof data_cnum1)
this.p_num1 = parseInt(data_cnum1);
},
parent_cnum2_change(data_cnum2){
this.p_num2 = parseInt(data_cnum2);
}
}
})
</script>
</html>
效果图: