一、Vue.js 实现 HelloWorld
先来看一个简单地用 Vue.js 实现的 HelloWorld 例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>HelloWorld</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">{{msg}}</div>
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'Hello World!'
}
});
console.log(app); // wn {_uid: 0, _isVue: true, $options: {…}, _renderProxy: wn, _self: wn, …}
console.log(app.$el); // <div id="app">Hello World!</div>
console.log(app.$data); // {__ob__: we}
console.log(app.$data.msg); // Hello World!
setTimeout(function () {
app.$data.msg = 'Bye!'
}, 2000);
</script>
</body>
</html>
通过控制台的几条打印数据及页面的渲染,可以看到,通过“实例.$属性”可以查询或改变数据。
下面的例子我将不再粘贴完整的 HTML 结构了,只放主要的逻辑代码到笔记中。
二、Vue.js 实现 TodoList
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
console.log(this.inputValue);
this.list.push(this.inputValue);
this.inputValue = '';
}
}
});
</script>
上面代码中,给 input 绑定一个 v-model 指令,值和 data 中的 inputValue 关联,然后通过 v-on 给 button 绑定一个 click 事件 “btnClick”,事件写到实例的 methods 中,在该事件中,通过 this 可以获取到当前实例的属性和值,实现向 data 中 list 数组里添加 inputVlaue 的值。最后通过 v-for 指令,将 list 数组中的值循环渲染到页面上。
三、jQuery 实现 TodoList
下面通过 jQuery 使用面向对象编写来实现 TodoList:
<script src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js'></script>
<div>
<input id="ipt" type="text">
<button id="btn">添加</button>
<ul id="ul"></ul>
</div>
<script>
// jQuery TodoList MVP 设计模式
// 使用面向对象编写
// 创建一个构造函数
function Page() {};
// 通过 $.extend 方法在 Page 的 prototype 上增加一些方法
$.extend(Page.prototype, {
// 初始化方法
init: function () {
this.bindEvents();
},
// 绑定事件
bindEvents: function () {
var btn = $("#btn");
btn.on('click', $.proxy(this.handleBtnClick, this));
},
handleBtnClick: function () {
var ipt = $("#ipt");
var iptVal = ipt.val(); // 输入的值
var ul = $("#ul");
ul.append("<li>" + iptVal + "</li>");
ipt.val("");
console.log(iptVal);
}
});
// 创建一个实例
var page = new Page();
page.init();
</script>
该方法和 Vue.js 实现的效果是一样的。
四、组建化修改 TodoList
1、全局组件的使用
创建一个全局组件 TodoList,如果组件的名称是驼峰命名法,那么在调用该组件时需要将大写改为小写,中间用“-”连接:
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<!-- <li v-for="item in list">{{item}}</li> -->
<todo-list v-bind:content="item" v-for="item in list"></todo-list>
</ul>
</div>
<script>
Vue.component('TodoList',{
props: ['content'],
template : '<li>{{content}}</li>'
});
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
console.log(this.inputValue);
this.list.push(this.inputValue);
this.inputValue = '';
}
}
});
</script>
补充:v-bind 给 HTML 标签设置属性。
2、局部组件的使用
先创建一个局部变量 TodoList,然后注册一个局部组件,把 TodoList 注册到 vue 事例中:
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<!-- <li v-for="item in list">{{item}}</li> -->
<todo-list v-bind:content="item" v-for="item in list"></todo-list>
</ul>
</div>
<script>
// 创建一个局部变量 TodoList
var TodoList = {
props: ['content'],
template: '<li>{{content}}</li>'
};
var app = new Vue({
el: '#app',
// 注册一个局部组件,把 TodoList 注册到 vue 事例中
components: {
TodoList: TodoList
},
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
console.log(this.inputValue);
this.list.push(this.inputValue);
this.inputValue = '';
}
}
});
</script>
该方式和全局组件实现的效果一样。
五、组件间传值
在 TodoList 的基础上,我们想实现这样一个功能,点击当前元素,当前元素就被删除的效果。
先来思考一下如何给每一个子组件都添加一个点击事件?我们把事件方法写到父组件的 methods 中,此时点击子组件,会发现根本触发不了,是因为子组件的事件方法要写在子组件里,所以我们把事件方法放到子组件中的 methods 试一下:
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<todo-list v-bind:content="item" v-for="item in list" @click="childClickFun">
</todo-list>
</ul>
</div>
<script>
var TodoList = {
props: ['content'],
template: "<li>{{content}}</li>",
methods: {
childClickFun: function () {
console.loh("child");
}
}
};
var app = new Vue({
el: '#app',
components: {
TodoList: TodoList
},
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
this.list.push(this.inputValue);
this.inputValue = '';
}
}
});
</script>
打开页面,点击子组件,发现有报错:“childClickFun” 没有在实例上定义,而是在呈现期间引用。
所以子组件的方法应该写在子组件的 methods 中,父组件的方法就应该写到父组件中。我们知道,父组件向子组件通过 props 传值,那子组件如何向父组件传值呢?子组件可以通过 $emit() 向父组件传值,我们来试一下:
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list" @click="clickFun">
</todo-list>
</ul>
</div>
<script>
var TodoList = {
props: ['content', 'index'],
template: "<li @click='childClickFun'>{{content}}</li>",
methods: {
childClickFun: function () {
this.$emit("click", this.index);
}
}
};
var app = new Vue({
el: '#app',
components: {
TodoList: TodoList
},
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
this.list.push(this.inputValue);
this.inputValue = '';
},
clickFun: function (index) {
console.log(index);
}
}
});
</script>
上面代码,我在子组件中定义了一个 childClickFun,在父组件中定义了一个 clickFun。我们先给子组件 todo-list 设置一个属性 index,这个 index 是在 v-for 循环中添加的一个循环项,这样设置完成后,还需要在子组件中通过 props 接收一下。接着在子组件的 childClickFun 中通过 emit() 向外触发事件,这个 emit() 中第一个参数传递触发的事件,第二个参数点击的位置,也就是 this.index,然后在子组件的 template 中添加这个点击事件(注意:emit() 中传入的事件名称要和 template 中 @ 后面的名称一致,可以设置其他名字)。最后我们在父组件的 clickFun 中传一个参数 index,这个 index 就是当前点击的元素的位置,我们打开页面看一下:
现在弄明白了父子组件之间的传值问题,就可以实现最初我们想要实现的那个点击当前元素删除的功能了。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="btnClick">添加</button>
<ul>
<todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list"
@delete="handleItemDelete">
</todo-list>
</ul>
</div>
<script>
var TodoList = {
props: ['content', 'index'],
template: "<li v-on:click='handleItemClick'>{{content}}</li>",
methods: {
handleItemClick: function () {
// 子组件向父组件传值 $emit,向外触发事件
// 第二个参数作为点击的位置
this.$emit("delete", this.index);
}
}
};
// 父组件
var app = new Vue({
el: '#app',
components: {
TodoList: TodoList
},
data: {
list: [],
inputValue: ''
},
methods: {
btnClick: function () {
this.list.push(this.inputValue);
this.inputValue = '';
},
handleItemDelete: function (index) {
console.log(this.list)
this.list.splice(index, 1);
}
}
});
</script>
附上该系列文章代码地址 Vue.js_Learning。
网友评论