vue2.0 从入门到精通 (本文特别长,但是文章右上角有目录导航,可以定位,更新中)
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.onload=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>
效果图: