v-model
指令在表单 <input>
、<textarea>
及 <select>
注意:v-model
会忽略所有表单元素的 value
、checked
、selected
特性的初始值而总是将 Vue 实例的数据作为数据来源.
v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:
-
text 和 textarea 元素使用
value
属性和input
事件; -
checkbox 和 radio 使用
checked
属性和change
事件; -
select 字段将
value
作为 prop 并将change
作为事件。
上面的解释来源于官网,感觉不错就拿过来了,好了,接着来实际操作下看看吧
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"> <!--下面是v-model使用实例,双向数据绑定--> <!--1.input文本使用--> <input type="text" v-model="msg" placeholder="请输入值"> <p>{{ msg }}</p> <br> <!--2.textarea富文本使用,这样一旦一个改变,界面上所有引用的地方都会改变, 在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。--> <textarea v-model="msg" placeholder="富文本输入"></textarea> <br> <!--3.单个复选框使用,checked选中就是true,没选中就是false--> <input type="checkbox" id="checked" v-model="checked"> <!--label的作用就是for关联对应的id标签,点击label文本就相当于点击了input--> <label for="checked">{{ checked }}</label> <br> <!--4.多个复选框使用--> <div> <input type="checkbox" id="c1" value="apple" v-model="checked_list"> <label for="c1">apple</label> <input type="checkbox" id="c2" value="banana" v-model="checked_list"> <label for="c2">banana</label> <input type="checkbox" id="c3" value="peach" v-model="checked_list"> <label for="c3">peach</label> <br> <!--将选择的value值存入checked_list中--> <span>多选的是: {{ checked_list }}</span> </div> <br> <!--5.单选使用,同样是存储value值--> <div> <input type="radio" id="r1" value="apple" v-model="radio_one"> <label for="r1">apple</label> <input type="radio" id="r2" value="banana" v-model="radio_one"> <label for="r2">banana</label> <br> <span>单选的是: {{ radio_one }}</span> </div> <br> <!--6.选择框的使用--> <div> <!--v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态, 所以建议用下面的方法,第一个为请选择但是设置disabled--> <select v-model="selected"> <!--在v-model下select下的option要设置value=""才会默认第一个显示--> <option disabled value="">请选择</option> <option>A</option> <!--有value就会将value值赋值给selected,没有则用文本的B--> <option value="2">B</option> <option value="3">C</option> </select> <span>你的选择是: {{ selected }}</span> </div> <br> <!--7.多选绑定到一个数组--> <div> <!--data里面selecteds为一个空数组--> <select multiple v-model="selecteds"> <option disabled value="">请选择</option> <option>A</option> <!--有value就会将value值赋值给selected,没有则用文本的B--> <option value="2">B</option> <option value="3">C</option> </select> <span>你的选择是: {{ selecteds }}</span> </div> <!--依旧是多选,但是是用v-for动态渲染--> <div> <!--select_for赋值了A,因此会默认选中value为A的选项--> <select v-model="select_for"> <option v-for="(item, index) in option_list" :key="index" :value="item.value">{{ item.text }}</option> </select> </div> <br> <!--8.值的绑定,对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值), 但是有时我们可能想把值绑定到 Vue 实例的一个动态属性上,这时可以用 v-bind 实现,并且这个属性的值可以不是字符串--> <input type="radio" v-model="toggle" v-bind:value="bind_value"> <!--value的值变成了动态属性bind_value--> <span>{{toggle}}</span> <br> <!--9.修饰符 .lazy,在“change”时而非“input”时更新 ,也就是输入中不改变msg,回车或确定时改变--> <input v-model.lazy="msg" > <br> <!--10.修饰符 .number,自动将用户的输入值转为数值类型--> <input v-model.number="age" type="number"> <br> <!--11.修饰符 .trim,自动过滤用户输入的首尾空白字符--> <input v-model.trim="msg"> </div> </body> <script src="vue.js"></script> <script> // 多选列表数据 var options = [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ]; new Vue({ el: '#box', data(){ return { msg: '', checked: false, checked_list: [], radio_one: '', selected: '', selecteds: [], option_list: [], // 初始化给了A,这样select就会选中value为A的选项 select_for: 'A', toggle: '', bind_value: '值被绑定了', age: '', } }, created(){ this.option_list = options } }) </script> </html>
-
组件化开发
-
全局组件(通用组件可以考虑变成全局组件)
// 声明全局组件, 第一个参数是组件的名字(Vbtn), 第二个参数是options,声明完之后就可以在其他组件调用,不需要挂载 Vue.component('Vbtn', { data(){ return { msg: '按钮' } }, template:`<button>{{ msg }}</button>` });
-
局部组件
遵循三步骤: 声子(创建组件), 挂子(挂载到父组件), 用子(父组件使用子组件),下面代码使用包含全局组件的调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"> <!--直接使用App组件--> <App/> </div> </body> <script src="vue.js"></script> <script> /* 注意:如果仅仅是实例化Vue实例化对象中 既有el又有template,如果template中定义模板的内容, 那么template模板的优先级大于el,就会使用template的内容,没有的话就会使用el的内容 */ // 声明全局组件, 第一个参数是组件的名字(Vbtn), 第二个参数是options,声明完之后就可以在其他组件调用,不需要挂载 Vue.component('Vbtn', { data(){ return { msg: '按钮' } }, // 通过slot插槽分发内容(组件传递内容),就相当于别的组件调用传值会替换slot标签的位置 template:`<button> <slot></slot> </button> ` }); // 定义App下的header区域,第一步声子,,然后App父组件就可以调用了 let Vheader = { data(){ return { header_login: '登录', header_reg: '注册', } }, // 定义herader区域的模板内容,使用全局组件Vbtn,界面显示登录和注册按钮 template:` <div> <Vbtn>{{ header_login }}</Vbtn> <Vbtn>{{ header_reg }}</Vbtn> </div> ` }; // 1.声子, Vue中 组件的名字首字母必须大写(与标签区分),组件中的data必须是一个函数且要有返回值,这里定义一个App let App = { data(){ return { name: 'liu', } }, // 定义App组件内容,使用App组件的内容,注意template里面一定是有一个根标签包裹全部标签,使用Vheader template:` <div class="app1"> <h2>{{ name }}</h2> <Vheader/> <Vbtn>提交</Vbtn> </div> `, components: { // 挂载header组件 Vheader } }; new Vue({ el:'#box', data(){ return { } }, // 组件挂载 components:{ // 2.挂子,如果key和value(App:App)一样可以只写一个(App) // App:App App } }) </script> </html>
-
组件的嵌套(单向数据流)
-
父子组件传值
-
父往子传值(props)
-
在子组件中 使用props声明(注意要声明一个数组),可以直接在子组件中任意使用
// 子组件Vheader let Vheader = { data(){ return { } }, // 在子组件中 使用props声明(注意要声明一个数组),可以直接在子组件中任意使用 props:['t_name', 'title', 'post2'], // 定义herader区域的模板内容,下面是使用父组件传过来的值 template:` <div> <span>{{ t_name }}</span> <span>{{ title }}</span> <span>{{ post2.title }}</span> </div> ` };
-
父组件要定义自定义属性
// 父组件App let App = { data(){ // 父组件的数据 return { name: 'liu', post1: { id: 1, title: 'My Journey with Vue' }, post2: { id: 2, title: 'test post' } } }, // 传入一个对象的所有属性可以v-bind="post1"也可以:post2="post2",第一种相当于 v-bind:id="post1.id"和v-bind:title="post1.title",所以在子组件中直接接收id和title并使用. template:` <Vheader :t_name="name" v-bind="post1" :post2="post2"></Vheader> `, components: { // 挂载header组件 Vheader } };
-
-
子往父传值(通过事件向父级组件传值,示例也包含了父向子传值)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"> <!--直接使用App组件--> <App/> </div> </body> <script src="vue.js"></script> <script> // 全局组件Vbtn Vue.component('Vbtn', { data(){ return { } }, props:['id'], template:`<button @click="clickHandler"> {{ id }} </button> `, methods:{ // 1.点击触发clickHandler方法,接着$emit就去触发父组件的事件方法 clickHandler(){ // $emit是vue方法,第一个参数写父组件声明自定义的事件,第二个参数传值 this.$emit('headerClick', this.id) } } }); // Vheader组件 let Vheader = { data(){ return { } }, props:['post'], // 2.父组件自定义事件,子组件点击按钮后通过$emit()触发父组件的headerClick中的headerHandler方法 template:` <div> <Vbtn :id="post.id" @headerClick="headerHandler"></Vbtn> </div> `, methods: { // 3.触发方法后,接着又去触发app父组件的appClick事件 headerHandler(val){ this.$emit('appClick', val) } } }; // App父组件 let App = { data(){ return { name: 'liu', post: { id: 1, title: 'My Journey with Vue' }, } }, // 4.header子组件通过$emit()触发父组件的appClick中的appHandler方法 template:` <div class="app1"> <Vheader :t_name="name" :post="post" @appClick="appHandler"></Vheader> </div> `, components: { // 挂载header组件 Vheader }, methods:{ // 5.该方法就是接收子组件的传值,并加1,重新赋值渲染界面 appHandler(val){ val++; this.post.id = val; } } }; new Vue({ el:'#box', data(){ return { } }, // 组件挂载 components:{ App } }) </script> </html>
-
-
平行组件传值
注意:A->B传值,那么B要声明事件,通过$on('事件的名称', function(){}), A则要触发事件 $emit('B组件中声明的事件名', '值val'),还有记住,前提条件是这两个方法必须绑定在同一个实例化对象中(比如let bus = new Vue()),同时绑定到bus上
let bus = new Vue(); // 全局组件Test, Test向Vheader传值msg, 因此$emit('Vheader组件中声明的事件名', '值val') Vue.component('Test', { data(){ return { msg: '我是全局子组件的数据', } }, template:`<button @click="clickHandler"> 按钮 </button> `, methods:{ clickHandler(){ // $emit和$on的事件要一样 bus.$emit('testData', this.msg) } } }); // Vheader组件 let Vheader = { data(){ return { // 定义一个text接收msg text: '' } }, template:` <div> <Test /> {{ text }} </div> `, methods: { }, // 接收$emit()传过来的值 created(){ // 这里的是bus调用,this指的是bus,所以要指向Vheader就需要用箭头函数指向父级 bus.$on('testData', (val) => { this.text = val; }) } };