原生js模拟vue
<div id="app">
<p>{{msg}}:{{name}},您今年{{age}}岁了</p>
<p>{{msg}}:我是{{name}},我确实{{age}}岁了,我是{{sex}}的</p>
</div>
<script type="text/javascript" src="js/MyVue.js">
</script>
//new MyVue对象
let vm = new MyVue({
el:"#app",
data:{
msg:"hello", name:"张四风", age:250, sex:"男"
}
});
MyVue.js文件
//定义一个MyVue类
class MyVue{
constructor(obj){
this.el = obj.el;
this.data = obj.data;
//{msg:"hello"}
this.render();
}
//渲染(跟DOM有关)
render(){
let divDom = this.$(this.el);
//把div里的双花括号的内容替换成data 里的内容。
let htmlStr = divDom.innerHTML;
for(let key in this.data){
//msg,name // htmlStr.replace(/{{msg}}/g,this.data.msg);
htmlStr=htmlStr.replace(new RegExp("{{"+key+"}}","g"),this.data[key]); };
divDom.innerHTML = htmlStr; }
$(str){ if(str.charAt(0)=="#"){
return document.getElementById(str.substring(1)); }
else if(str.charAt(0)=="."){
return document.getElementsByClassName(str.substring(1)); }
else{ return document.getElementsByTagName(str); }
}
}
指令
//指令的作用:
//1、把vue对象里的data,显示(响应式)在页面上,什么是响应式?就是data一旦改变,立即会呈现在页面上。
//2、当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
<div id="app">
<a v-bind:href="url" >goURL</a>
<a v-bind:[attr]="url" >goURL</a>
<a v-bind:[attrname]="value"> ... </a>
<input v-bind:disabled="isDisabled" type="button" value="测试" />
</div>
let vm = new Vue({ el:"#app",//element; 元素 data:{ //数据 isDisabled:true, attr:"href", url:"http://www.taobao.com", bar:"t" }, computed:{ attrname:function () { return 'foo' + this.bar; } } });
v-clock:解决网页网速差时的dom数据闪烁问题
v-text:纯文本
插值
v-html:解析标签
<div id="app">
<p>{{msg}}:{{htmlstr}}</p>
<p>年龄:{{age+1}}</p>
<p>是否成年:{{age>=18?"是的":"没有"}}</p>
<span v-html="htmlstr"></span> <input v-bind:disabled="isDisabled" type="button" value="测试" />
</div>
let vm = new Vue({ el:"#app", data:{ msg:"hello", htmlstr:"<img src='img/1.jpg' />", isDisabled:true, age:16 } });
声明式渲染
v-bind:内联样式的属性前加,简写:
<img v-bind:src="imgfile" />-------------<img :src="imgfile" />
绑定属性,数据单向从m->v,可以写合法的js+“123”
<div id="app">
<p>{{msg}}:{{name}},您今年{{age}}岁了</p>
<img v-bind:src="imgfile" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
let vm = new Vue({ el:"#app",//element; 元素 data:{ //数据 msg:"hello", name:"张四风", age:250, imgfile:"img/1.jpg" } });
事件绑定
v-on:事件,简写方式@
<div id="app">
<div style="width:300px;height: 200px;background-color: red" @click.self="parent">
<div style="width:200px;height: 100px;background-color: blue" @click="sub"></div>
</div>
<input type="text" @keydown.13 = "send" />
<input type="text" @keydown.enter = "send" />
</div>
let vm = new Vue({ el:"#app",//element; 元素 //methods里写函数。
methods:{ parent:function () { alert("父亲被点击了"); }, sub:function () { alert("儿子被点击了"); }, send:function () { alert("发了"); } } });
v-on:click.stop 阻止冒泡
v-on:click.prevent 阻止默认行为(a链接,submit事件)
v-on:click.capture 事件侦听时,事件捕获模式(从外到内)
v-on:click.self 只对该元素有效
v-on:click.once 只触发一次
带修饰符放入可以串联:.prevent.once(都只执行一次,先后顺序无关)
v-if:true显示元素,false元素消失【移除】
重新删除或创建,较高的切换性能消耗
v-else:if为true则他消失,if为false则他显示
v-show:true显示元素,false元素只是隐藏,并不消失【隐藏】
display:block/none,较高的初始渲染消耗
<div id="app">
<div id="box1" v-show="isShow" style="width: 10px;height: 10px;background-color: red"> </div>
<div id="box2" v-if="isShow2" style="width: 10px;height: 10px;background-color: blue"> </div>
<div id="box3" v-else style="width: 10px;height: 10px;background-color: green"> </div>
</div>
let vm = new Vue({ el:"#app",//element; 元素 data:{ //数据 isShow:false, isShow2:true } });
v-model指令,它能轻松实现表单输入和应用状态之间的双向绑定。
v-model的修饰符
.lazy: 取代input监听change事件
.number:输入字符串转为有效的数字
.trim:输入首尾空格过滤
v-pre跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
不会进行编译,页面显示会“{{}}”
<div id="app">
请输入您的年龄: <input type="text" v-model.lazy="age" /> <p>您今年{{ age }}岁了</p>
请输入您的体重: <input type="text" v-model.number="weight" /> <p>您的体重{{weight}}公斤</p>
请输入您的名字: <input type="text" v-model.trim="name" /> <p>您的名字:{{name}}</p> <p v-pre>您的名字:{{name}}</p> </div>
let vm = new Vue({ el:"#app",//element; 元素 data:{ age:250, weight:70, name:"john" } });
v-on和v-model的简易计算器
<div class="app">
<input type="" name="" id="" v-model="n1" />
<select v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select> <
input type="" name="" id="" v-model="n2" />
<input type="button" name="" id="" value="=" @click="cal"/>
<input type="" name="" id="" v-model="result" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
let vm=new Vue({
el:".app",
data:{n1:0,n2:0,opt:'+',result:0},
methods:{ cal(){ let str='parseInt(this.n1)'+this.opt+'parseInt(this.n2)'; this.result=eval(str); } }
})
</script>
v-for:循环
1、循环普通数组 v-for="type in types"
2、循环对象数组 v-for="(goods,index) in goodslist"
goods每一项,index索引值
3、循环对象 v-for="(value,key,index) in person"
值,键,index索引值
4、迭代数字 v-for="count in 4"
2.2.0+的版本,组件使用v-for,key是必须的
<div id="app">
<h1>{{type}}</h1>
//循环普通数组 v-for="type in types"
<ul><li v-for="type in types">{{type}}</li></ul> <h1>{{title}}</h1> <ul>
//循环对象数组 v-for="(goods,index) in goodslist"
//goods每一项,index索引值
<li v-for="(goods,index) in goodslist" :key="goods.id">
<p>第{{index+1}}个商品:</p>
<p>商品编号:{{goods.id}}</p>
<p>商品名称:{{goods.name}}</p>
<p>商品价格:{{goods.price}}</p>
</li> </ul> <hr />
<ul>
//循环对象 v-for="(value,key,index) in person"
//值,键,index索引值
<li v-for="(value,key,index) in person"> <p>{{index+1}}、{{key}}:{{value}}</p> </li>
</ul>
</div>
let vm = new Vue({
el: "#app",
data: { type: "类型类别", types: ["生活用品", "文具", "家电"], title: "文具", goodslist: [{"id": "001","name": "铅笔","price": 1.5}, {"id": "002","name": "钢笔","price": 25}, {"id": "003","name": "毛笔","price": 55}], person: { "身份证号码": "007", "姓名": "刘德华", "性别": "男"} } });
v-for的key
<div id="app"> <ul> <li v-for="(item,index) in arr" v-bind:id="index" :key="index"> {{item}} </li> </ul> <input type="button" v-on:click="sort" /> </div>
let vm = new Vue({
el:"#app",
data:{ arr:[5,4,3,2,1]},
methods:{ sort:function () {
// this.arr.sort();
// this.arr = this.arr.filter(function (val) {
// return val>3; //
});
// this.arr[0] = 20;
//这不是响应式的,这种写法的结果不会呈现在页面上。 Vue.set(this.arr,0,20); // this.arr.splice(0,1,20); } } });
v-for:动态添加
<div id="app"> <ul> <li v-for="(value,key,index) in person"> <p>{{index+1}}、{{key}}:{{value}}</p> </li> </ul> <input type="button" value="添加一个属性" v-on:click="addAttr" /> </div>
let vm = new Vue({ el:"#app", data:{ person:{ "身份证号码":"007", "姓名":"刘德华", "性别":"男" } }, //methods里写函数。 methods:{ addAttr:function () { Vue.set(this.person,"年龄",25); } } });
用key去管理可复用的元素
<div id="app"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-key"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-key"> </template> <input type="button" value="改变登录方式" @click="changeType" /> </div>
let vm = new Vue({ el:"#app",//element; 元素 data:{ loginType:"username" }, methods:{ changeType:function () { // this.loginType = "email"; this.loginType = this.loginType=="username"?"email":"username"; } } });
v-for(显示数组经过加工的结果)
<div id="app"> <input type="text" v-model.number="newnum" /> <input type="button" value="添加一个数字" @click="addNum" /> <ul> <li v-for="item in numbers">{{item}}</li> </ul> <hr/> <ul> <li v-for="item in gtTwo">{{item}}</li> </ul> </div>
let vm = new Vue({ el:"#app", data:{ numbers:[1,2,5,8,10], newnum:0 }, computed:{ gtTwo:function () { return this.numbers.filter(function(item){ return item>2; }); } }, methods:{ addNum:function(){ this.numbers.push(this.newnum); } } });
v-for循环里,in后面是数字
<div id="app"> <input type="text" v-model.number="newnum" /> <input type="button" value="添加一个数字" /> <ul> <li v-for="item in newnum">{{item}}</li> </ul> </div>
let vm = new Vue({ el:"#app", data:{ newnum:5 } });