_vue.js
這個寫不完整的渲染函數花了我一個早餐時間,測試它也用了我一杯無糖可樂的時間.
早就不只了..
但是建立這個網頁卻弄了我整個下午...
這個函數雖然沒經過仔細測試 但我猜它應該具備以下特性:
這個寫不完整的渲染函數花了我一個早餐時間,測試它也用了我一杯無糖可樂的時間.
早就不只了..
但是建立這個網頁卻弄了我整個下午...
這個函數雖然沒經過仔細測試 但我猜它應該具備以下特性:
嗯。是蠻暴力的
(function (global) {
var eventType = {
'v-click': function(el,event){
el.addEventListener("click", event);
},
'v-change': function(el,event){
el.addEventListener("onchange", event);
},
};
var vMethods = {
'v-for': function(el,data){
// console.log(el,data,this);
var template = el.innerHTML;
var dataObj = this.state[data];
var rs = '';
for(var key in dataObj){
rs += this.render(template,dataObj[key]);
}
el.innerHTML = rs;
}
}
function _vue(obj) {
this.id = obj.domId;
this.template = document.getElementById(this.id).innerHTML;
this.state = {};
this.event = {};
this.render = function (template, dataObj) {
var rsHtml = template;
for (var key in dataObj) {
var reg = new RegExp('{' + key + '}', 'g')
rsHtml = rsHtml.replace(reg, dataObj[key]);
};
return rsHtml;
}
this.change = function (data) {
for (var key in data) {
this.state[key] = data[key];
}
document.getElementById(this.id).innerHTML = this.render(this.template, this.state);
for(var key in vMethods){
document.querySelectorAll('#'+this.id+' ['+key+']').forEach(function(el,index){
for (var i = 0; i < el.attributes.length; i++) {
if(el.attributes[i].name){
vMethods[el.attributes[i].name].bind(this)(el,el.attributes[i].value);
}
}
}.bind(this))
}
for(var key in eventType){
document.querySelectorAll('#'+this.id+' ['+key+']').forEach(function(el,index){
for (var i = 0; i < el.attributes.length; i++) {
if(el.attributes[i].name){
this.event[el.attributes[i].value] &&
eventType[el.attributes[i].name](el, this.event[el.attributes[i].value].bind(this) );
}
}
}.bind(this))
}
this.componentBind();
}
this.componentBind = function () {
var __vue = this.constructor;
var render = this.render;
for (var key in __vue.comTemplate) {
var comTemplate = __vue.comTemplate[key];
document.querySelectorAll('#' + this.id + ' ' + key).forEach(function (el, index) {
var data = {};
for (var i = 0; i < el.attributes.length; i++) {
data[el.attributes[i].name] = el.attributes[i].value;
}
el.innerHTML = render(comTemplate, data);
})
}
}
for (var key in obj.data) {
this.state[key] = obj.data[key];
}
this.event = obj.methods;
this.change();
}
_vue.comTemplate = {};
_vue.component = function (obj) {
this.comTemplate[obj.el] = obj.template;
};
global._vue = _vue;
})(window);
從Vue模仿的模板寫法
<div id="app">
<strong>{title}</strong>{body}
</div>
var app = new _vue({
domId:'app',
data:{
title:'Hello',
body:'_vue!'
}
});
還可以透過change方法動態更新內容,雖然沒有Vue那麼神奇的屬性更新
你可以在console介面使用下面的指令,然後app區塊的body就會跟著變動了
app.change({
body: 'vueeeeeeeeeeeeeee!'
});
_vue復刻了Vue經常被使用的循環指令,所以列出清單應該也不是什麼難事了
<div id="todo">
<h2>{title}</h2>
<ol v-for="list">
<li>{text}</li>
</ol>
</div>
var todo = new _vue({
domId: 'todo',
data: {
title: 'Todo list',
list:[
{text:'牽摩托車去修理'},
{text:'吃早餐'},
{text:'抱怨主管'},
],
}
});
現在你可以透過v-click屬性來替元素新增click事件,而在事件裡你可以透過this來取得自己的所有方法
接下來的例子擴增了剛剛的list清單,當你按下button就會新增一個清單
<div id="todoWithAdd">
<h2>{title}</h2>
<button v-click="addlist">addlist</button>
<ol v-for="list">
<li>{text}-{date}</li>
</ol>
</div>
var todoWithAdd = new _vue({
domId: 'todoWithAdd',
data: {
title: 'HELLO',
body: '_vue.js',
list:[
{text:'list 1',date:'2017/10/5'},
{text:'list 2',date:'2017/10/6'},
{text:'list 3',date:'2017/10/8'},
],
},
methods: {
addlist: function () {
this.state.list.push({
text:'list new',
date:new Date()
});
this.change();
}
}
});
雖然很吃力..我還是模仿了Vue的元件系統,反正Vue可能也是模仿React的
使用方法是透過_vue.component指令跟_vue註冊一個元件,之後就可以在_vue裡使用自訂元件
<div id="componentExample">
<strong>{title}</strong>
<strike>{body}</strike>
<vue text="_vue.js"></vue>
</div>
_vue.component({
el: 'vue',
template: '{text}'
});
var componentExample = new _vue({
domId: 'componentExample',
data: {
title: 'HELLO',
body: 'Vue.js',
}
});