介绍
挂载点/模板/实例
vue只会对它所对应的挂载点(el)内的内容产生作用。
挂载点里的内容称为模版(template),模版可以通过template写在vue中,和写在挂载点下面的作用是一样的。
vue实例(new Vue({}))绑定到挂载点后会自动对模版和数据内容进行处理,生成要最终展示的内容。
<div id="root"></div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) template: '<h1>hello {{message}}!</h1>', //模板 data:{ message:"world" } }) </script>
vue实例变量.$属性 可以访问vue实例的属性。
数据展示
{{}}插值表达式
{{ }} 用于输出对象属性和函数返回值
v-text/v-html指令显示数据
<div id="root"> <div v-text="message"></div> <!--v-text以文本形式显示data中指定数据--> <div v-html="content"></div> <!--v-html以html形式解析data中指定数据--> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ message:"world", content:"<h1>hello world<h1>" } }) </script>
事件
v-on:click事件和方法(@)
v-on:click调用vue的methods中声明的方法,v-on:可以简写成@符号
<div id="root"> <div v-on:click="this.handleClick">{{content}}</div> <!--v-on:可以写成 @click="this.handleClick"--> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ content:"hello", }, methods:{ handleClick: function(){ this.content = 'world'; } } }) </script>
修饰符
修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(),这样只会执行绑定的方法,不会执行事件默认的操作。
<form v-on:submit.prevent="onSubmit"></form>
其他事件修饰符
Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。
Vue.js通过由点(.)表示的指令后缀来调用修饰符。
.stop
.prevent
.capture
.self
.once
<!-- 阻止事件传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件时不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符,阻止submit事件默认操作 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式,带此关键字会优先执行,然后执行子组件在执行父组件 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> <!-- click 事件只能点击一次,2.1.4版本新增 --> <a v-on:click.once="doThis"></a>
按键修饰符
Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13="submit">
记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:
<!-- 同上 --> <input v-on:keyup.enter="submit"> <!-- 缩写语法 --> <input @keyup.enter="submit">
属性绑定和双向数据绑定
v-bind:属性绑定(:)
v-bind:属性绑定可以简写为:,属性双引号中的值是js表达式可以用js操作符操作。
v-model双向绑定
双向绑定是指vue实例中的data和挂载点中的dom属性绑定,可以实现属性的值改变vue实例中的数据,不仅仅是vue实例的data数据影响dom。
<div id="root"> <div v-bind:title="title">{{content}}</div> <!--v-bind:缩写成:,意思是title属性值绑定为vue实例data中的title的值--> <input v-model="content" /> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ content:"hello", title:"this is hello world" } }) </script>
computed计算属性watch监听属性
<div id="root"> 姓:<input v-model="firstName" /> 名:<input v-model="lastName" /> <div>{{fullName}}</div> <div>{{count}}</div> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ firstName:"", lastName:"", count:0 }, computed:{ //计算属性,通过已有的data数据计算出新的属性,依赖变更时会重新计算 fullName:function(){ return this.firstName +' '+this.lastName; } }, watch:{ //监听器,监听数据的变化,当数据发生变化时执行 fullName:function(){ //当fullName属性值变化时 this.count++; } } }) </script>
过滤器
过滤器函数接受表达式的值作为第一个参数。
<div id="app"> {{ message | capitalize }} </div> <script> new Vue({ el: '#app', data: { message: 'abcd' }, filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } }) </script>
v-if、v-show标签
v-if值为ture,将元素插入dom,false删除dom。
v-show值为ture是显示dom,false时不显示,通过css样式,style="display: none;"。(性能高一点,不用每次新建dom)
<div id="root"> <div v-if="show">hello</div> <div v-show="show">world</div> <button @click="handleClick">toggle</button> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ show:true }, methods:{ handleClick:function(){ this.show = !this.show; } } }) </script>
多个v-if
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }) </script>
v-for标签
v-for 指令可以用来遍历数组(val,index)、对象(val,key,index)、整数。
遍历每一个数据
<div id="root"> <ul> <!-- 遍历list中的每一项放入item中,index为下标,:key的作用是用来加速渲染一定要唯一 --> <li v-for="(item,index) of list" :key="index">{{item}}</li> </ul> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data:{ list:['a','b','c'] } }) </script>
动态修改数组
<div id="root"> <div> <input v-model="inputVal"/> <button @click="handleSubmit">提交</button> <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) --> </div> <ul> <!-- 仅仅是显示list中的值,当list中的值变化时这里也会跟着变 --> <li v-for="(item,index) of list" :key="index">{{item}}</li> </ul> </div> <script> /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data: { inputVal: '', //input双向绑定的值 list:[] //list数组 }, methods: { handleSubmit: function(){ //按钮绑定的方法 this.list.push(this.inputVal); this.inputVal = '' } } }) </script>
自定义指令
<div id="app"> <p>页面载入,input 元素自动获取焦点:</p> <input v-focus> </div> <script> // 注册一个全局自定义指令 v-focus Vue.directive('focus', { // 当绑定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } }) // 创建根实例 new Vue({ el: '#app' }) </script>
组件
组件其实也是一个实例,注册一个全局组件语法格式如下:
Vue.component(tagName, options)
简单组件
<ol id="app"> <!-- 使用组件,创建一个todo-item组件的实例 --> <todo-item></todo-item> </ol> <!-- 这里的script一定要写在最后写在前面不行 --> <script> // 定义名为 todo-item 的新组件,tagName为todo-item(html中直接使用) Vue.component('todo-item', { template: '<li>这是个待办项</li>' }); //声明式渲染不能少 new Vue({ el: '#app' }) </script>
父组件传值子组件
v-for遍历多次调用全局组件,动态添加数据。
父组件(vue实例)向子组件传值,通过属性绑定的方式传值,子组件通过props接收属性的值。
父组件 -> 将值绑定(v-bind:)在子组件的挂载点上 -> 子组件通过props获取挂载点上的属性值。
<div id="root"> <div> <input v-model="inputVal"/> <button @click="handleSubmit">提交</button> <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) --> </div> <ul> <!-- vue实例中的值每次改变dom也会跟着变动,这里把item作为参数传给组件了--> <todo-item v-for="(item,index) of list" :key="index" :param="item"> <todo-item/> </ul> </div> <script> /*全局组件,相当于一个li标签,中间的内容由父级实例传入,props接收父级实例传过来的数据*/ Vue.component('todo-item',{ props: ['param'], template:'<li @click="handleClick">{{param}}</li>', methods: { handleClick: function(){ alert('cl'); } } }); /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data: { inputVal: '', //input双向绑定的值 list:[] //list数组 }, methods: { handleSubmit: function(){ //按钮绑定的方法 this.list.push(this.inputVal); this.inputVal = '' } } }) </script>
子组件向父组件传值
要通过发布订阅的方式实现。
子组件通过this.$emit(事件,参数)方法触发事件 -> 父组件在子组件上通过v-on:方式监听事件 -> 父组件找到事件绑定的方法(带参数)并执行.
<div id="root"> <div> <input v-model="inputVal"/> <button @click="handleSubmit">提交</button> <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) --> </div> <ul> <!-- vue实例中的值每次改变dom也会跟着变动,这里把item作为参数传给组件了;监听组件的delete事件,如果被触发执行vue实例的handleDelete--> <todo-item v-for="(item,index) of list" :key="index" :param="item" :index="index" @delete="handleDelete"> <todo-item/> </ul> </div> <script> /*全局组件,相当于一个li标签,中间的内容由参数(遍历的item)传入并展示*/ Vue.component('todo-item',{ props: ['param','index'], template:'<li @click="handleClick">{{param}},下标{{index}}</li>', methods: { handleClick: function(vlue){ this.$emit('delete',this.index); //方法触发delete事件并传值 } } }); /*vue实例*/ new Vue({ el:"#root", //挂载点(dom) data: { inputVal: '', //input双向绑定的值 list:[] //list数组 }, methods: { handleSubmit: function(){ //按钮绑定的方法 this.list.push(this.inputVal); this.inputVal = '' }, handleDelete: function(index){ this.list.splice(index,1); } } }) </script>
1、父组件可以使用 props 把数据传给子组件。
2、子组件可以使用 $emit 触发父组件的自定义事件。
vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行fn;
官方示例
<html> <head> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> window.onload=function (){ //声明式渲染 app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) //v-bind:title给标签动态绑定提示 app2 = new Vue({ el: '#app-2', data: { message: '页面加载于 ' + new Date().toLocaleString() } }) //v-if条件 app3 = new Vue({ el: '#app-3', data: { seen: true } }) //v-for循环 app4 = new Vue({ el: '#app-4', data: { todos: [ { text: '学习 JavaScript' }, { text: '学习 Vue' }, { text: '整个牛项目' } ] } }) //v-on:click点击事件 app5 = new Vue({ el: '#app-5', data: { message: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } }) //v-model双向绑定 app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } }) } </script> </head> <body> <!--显示文本--> <div id="app">{{ message }}</div> <!--显示悬浮框--> <div id="app-2"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的提示信息! </span> </div> <!--条件--> <div id="app-3"> <p v-if="seen">现在你看到我了</p> </div> <!--循环--> <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div> <!--点击事件--> <div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">逆转消息</button> </div> <!--表单输入和文本状态之间的双向绑定--> <div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div> </body> </html>
vue-cli
npm安装及配置
https://www.cnblogs.com/aeolian/p/12457284.html
安装
#安装vue-cli npm install --global vue-cli #或者 npm install -g @vue/cli
构建项目
#cli方式(vue-cli3才有的命令),vuecli集成webpack vue create hello-world #基于webpack vue init webpack hello-world
运行
cd hello-world
npm run dev
结构
index.html为首页,main.js为index中挂载点的实例,main.js中导入组件并使用组件。
main.js
import Vue from 'vue' import TodoList from './TodoList' /* index.html中挂载点的实例 */ new Vue({ el: '#app', /* index.html中的根结点 */ components: { App: TodoList }, /* 以APP标签使用引入的TodoList组件 */ template: '<App/>' })
TodoList.vue
<!--父组件--> <template> <div id="app"> <div> <input v-model="inputVal"/> <button @click="handleSubmit">提交</button> <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) --> <ul> <!--使用子组件,通过:绑定属性传值给子组件,通过@监听事件接收子组件传值--> <todo-item v-for="(item,index) of list" :content="item" :index="index" :key="index" @delete="handleDelete"> </todo-item> </ul> </div> </div> </template> <script> /* 引入子组件TodoItem组件 */ import TodoItem from './components/TodoItem' export default { components: { 'todo-item': TodoItem }, /* 引用导入的组件,声明通过todo-item标签的方式使用TodoItem */ name: 'App', data: function () { return { inputVal: '', list: [] } }, methods: { handleSubmit () { this.list.push(this.inputVal) this.inputVal = '' }, handleDelete (index) { /* 监听子组件触发的事件方法,并接收参数 */ this.list.splice(index, 1) /* 从index位置删除1个数据 */ } } } </script> <!--不加scope会变成全局--> <style scoped> #app { color: #2c3e50; } </style>
TodoItem.vue
<!--子组件--> <template> <!--监听li标签的单击事件,执行handleDelete方法--> <li @click="handleDelete">{{content}}</li> </template> <script> export default { props: ['content', 'index'], /* 通过属性接收父组件的数据 */ methods: { handleDelete () { this.$emit('delete', this.index) /* 触发父组件的delete监听事件,并传递参数index */ // alert(this.index) } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>