Webpack 入门教程:http://www.runoob.com/w3cnote/webpack-tutorial.html
官方文档:http://vuejs.org/v2/guide/syntax.html
https://vuejs.org/v2/api/
中文文档: https://cn.vuejs.org/v2/guide/syntax.html
https://cn.vuejs.org/v2/api/
# 全局安装 vue-cli$ cnpm install --global vue-cli# 创建一个基于 webpack 模板的新项目$ vue init webpack my-project# 这里需要进行一些配置,默认回车即可$ cd my-project$ cnpm install$ cnpm run devDONE Compiled successfully in 4388ms> Listening at http://localhost:8080

<!DOCTYPE html><html><head><meta charset="utf-8"><title>Vue 测试实例 - 菜鸟教程(runoob.com)</title><script src="https://unpkg.com/vue/dist/vue.js"></script></head><body><div id="app"><p>{{ message }}</p></div><script>new Vue({el: '#app',data: {message: 'Hello Vue.js!'}})</script></body></html>
Vue.js 目录结构
上一章节中我们使用了 npm 安装项目,我们在 IDE(Eclipse、Atom等) 中打开该目录,结构如下所示:
目录解析
| 目录/文件 | 说明 |
|---|---|
| build | 项目构建(webpack)相关代码 |
| config | 配置目录,包括端口号等。我们初学可以 使用默认的。 |
| node_modules | npm 加载的项目依赖模块 |
| src | 这里是我们要开发的目录,基本上要做的事情 都在这个目录里。里面包含了几个目录及文件: - assets: 放置一些图片,如logo等。 - components: 目录里面放了一个组件文件 |
,可以不用。
- App.vue: 项目入口文件,我们也可以
直接将组件写这里,而不使用 components
目录。
- main.js: 项目的核心文件。
|
| static | 静态资源目录,如图片、字体等。 |
| test | 初始测试目录,可删除 |
| .xxxx文件 | 这些是一些配置文件,包括语法配置,
git配置等。 |
| index.html | 首页入口文件,你可以添加一些 meta
信息或统计代码啥的。 |
| package.json | 项目配置文件。 |
| README.md | 项目的说明文档,markdown 格式 |
在前面我们打开 APP.vue 文件,代码如下(解释在注释中):
<!-- 展示模板 --><template><div id="app"><img src="./assets/logo.png"><hello></hello><div><h1 class="class1" v-bind:class="{ 'class2': use }">site : {{site}}</h1><div v-bind:class="[ 'class1' ,use ? 'class2' : '']"></div><div v-bind:class="classObject"></div><div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">style</div><div v-bind:style="[baseStyles, overridingStyles]">style</div><h1>url : {{url}}</h1><h1>{{details()}}</h1></div><div v-html="message"></div><br />{{5+5}}<br />{{ ok ? 'YES' : 'NO' }}<br />{{ msg.split('').reverse().join('') }}<div v-bind:id="'list-' + id">菜鸟教程</div><p v-if="seen">现在你看到我了</p><pre><a v-bind:href="url">菜鸟教程</a><a :href="url">v-bind可以缩写,菜鸟教程</a></pre><form v-on:submit.prevent="onSubmit"><p>{{ msg }}</p><input v-model="msg"><button v-on:click="doSomething">绑定click事件</button><button @click="doSomething">v-on:可以缩写,绑定click事件</button><button type="submit">提交</button></form><br /><br /><!-- 在两个大括号中 -->{{ msg | capitalize | capitalize2 | capitalize3('arg1') }}<!-- 在 v-bind 指令中 --><div v-bind:id="msg | capitalize | capitalize2 | capitalize3('arg1')">绑定id</div><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><h1 v-show="ok">Hello!</h1><ul><li v-for="site in sites">{{ site.name }}</li><li v-for="value in object">{{ value }}</li><li v-for="(value, key, index) in object">{{ value }}</li><li v-for="n in 10">{{ n }}</li></ul><p>原始字符串: {{ msg }}</p><p>计算后反转字符串: {{ reversedMessage }}</p></div></template><script>// 导入组件import Hello from './components/Hello'export default {name: 'app',el: '#app',watch : {kilometers:function(val) {this.kilometers = val;this.meters = this.kilometers * 1000},meters : function (val) {this.kilometers = val/ 1000;this.meters = val;}},computed: {classObject: function () {return {class1: true,class2: this.use,}},// 计算属性的 getterreversedMessage: function () {// `this` 指向 vm 实例return this.msg.split('').reverse().join('')},siteComputed: { // computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter :// getterget: function () {return this.object.name + ' ' + this.object.url},// setterset: function (newValue) {var names = newValue.split(' ');this.object.name = names[0];this.object.url = names[names.length - 1];}}},filters: { // 过滤器capitalize: function (value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)},capitalize2: function (value) { // 过滤器可以串联if (!value) return ''value = value.toString();return value.slice(0, value.length - 1) + value.charAt(value.length - 1).toUpperCase()},// 过滤器是 JavaScript 函数,因此可以接受参数:capitalize3: function (aa, value) {if (!value) return ''value = value.toString()return value + aa;},},components: {Hello, // 这里是一个子组件},data: {baseStyles: { color: 'red' },overridingStyles: { fontSize: '14px' },activeColor: 'red',fontSize: 14,kilometers: 0,meters: 0,type: 'A',id: 'id',msg: 'msg message',sites: [{ name: 'a' }, { name: 'b' }],object: {name: '菜鸟教程',url: 'http://www.runoob.com',slogan: '学的不仅是技术,更是梦想!'},site: "菜鸟教程",url: "www.runoob.com", // 绑定响应式更新元素 v-bind:href="url"alexa: "10000",use: false, // 绑定class v-bind当use为true时显示class1ok: true, // 三元表达式控制显示内容,操作字符串或表达式seen: true,// v-if的语法,操作组件或html元素message: '<h1>双括号用于输出文本,v-html用于输出html</h1>',},methods: {submit: function() { // v-on:submit.prevent="onSubmit" .prevent是修饰符// .prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():this.msg = '提交';},doSomething: function(e){this.msg = Date.now().toString();e.preventDefault();e.stopPropagation();},details: function() {return this.site + " - 学的不仅是技术,更是梦想!";}},}/*// $watch 是一个实例方法vm.$watch('kilometers', function (newValue, oldValue) {// 这个回调将在 vm.kilometers 改变后调用document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;});*/</script><!-- 样式代码 --><style>#app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;}</style>
数组操作
vm.$set( target, propertyName/index, value )
- 参数:
- {Object | Array} target
- {string | number} propertyName/index
- {any} value
<!-- 完整语法 --><a v-bind:href="url">...</a><!-- 缩写 --><a :href="url">...</a><!-- 动态参数的缩写 (2.6.0+) --><a :[key]="url"> ... </a>// ====================================<!-- 缩写 --><a @click="doSomething">...</a><!-- 动态参数的缩写 (2.6.0+) --><a @[event]="doSomething"> ... </a>// =======================================<h1 v-if="awesome">if</h1><h1 v-else-if="type === 'C'"></h1><h1 v-else>else</h1>// ===============================<ul id="example-1"><liv-for="(item, index) in items"v-for="item in items"v-for="item of items"v-for="(value, name, index) in object"ref="p" // this.$refs.p = [vt, vt, vt, ...] 如果这样写会变成这样的:key="item.message">{{ item.message }}</li></ul>
过滤器 filters
Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。由”管道符”指示。可以通过过滤器对值进行加工处理
{{ message | capitalize }}<!-- 在 v-bind 指令中 --><div v-bind:id="rawId | formatId"></div>
计算属性 computed
computed vs methods
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
监听属性 watch
我们将为大家介绍 Vue.js 监听属性 watch,我们可以通过 watch 来响应数据的变化。
vm.$watch('kilometers', function (newValue, oldValue) {// ... newValue 表示新值, oldValue 表示老值});
修饰符
事件修饰符
Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。
Vue.js通过由点(.)表示的指令后缀来调用修饰符。
.stop.prevent.capture.self.once
按键修饰符
Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:
全部的按键别名:
.enter.tab.delete(捕获 “删除” 和 “退格” 键).esc.space.up.down.left.right.ctrl.alt.shift.meta
实例
表单修饰符
.lazy
在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:
.number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:
这通常很有用,因为在 type=”number” 时 HTML 中输入的值也总是会返回字符串类型。
.trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:
表单的双向绑定
<div id="app"><p>单个复选框:</p><input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">{{ checked }}</label><p>多个复选框:</p><input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"><label for="runoob">Runoob</label><input type="checkbox" id="google" value="Google" v-model="checkedNames"><label for="google">Google</label><input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"><label for="taobao">taobao</label><br><span>选择的值为: {{ checkedNames }}</span></div><script>new Vue({el: '#app',data: {checked : false,checkedNames: []}})</script>
VUE组件注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
全局组件的注册方法
<div id="app"><runoob></runoob><child message="hello!"></child><child v-bind:message="parentMsg"></child><ol><todo-item v-for="item in sites" v-bind:todo="item"></todo-item></ol></div><script>// 注册Vue.component('runoob', {template: '<h1>自定义组件!</h1>'});Vue.component('child', {// 声明 propsprops: ['message'],// 同样也可以在 vm 实例中像 "this.message" 这样使用template: '<span>{{ message }}</span>'});Vue.component('todo-item', {props: ['todo'],template: '<li>{{ todo.text }}</li>'});// 创建根实例new Vue({el: '#app',data: {parentMsg: '父组件内容',sites: [{ text: 'Runoob' },{ text: 'Google' },{ text: 'Taobao' }],},});</script>
局部组件的组册方法
<div id="app"><runoob></runoob></div><script>var Child = {template: '<h1>自定义组件!</h1>'}// 创建根实例new Vue({el: '#app',components: {// <runoob> 将只在父模板可用'runoob': Child}})</script>
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
Vue.component('example', {props: {// 基础类型检测 (`null` 意思是任何类型都可以)propA: Number,// 多种类型propB: [String, Number],// 必传且是字符串propC: {type: String,required: true},// 数字,有默认值propD: {type: Number,default: 100},// 数组/对象的默认值应当由一个工厂函数返回propE: {type: Object,default: function () {return { message: 'hello' }}},// 自定义验证函数propF: {validator: function (value) {return value > 10}}}})
type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
type 也可以是一个自定义构造器,使用 instanceof 检测。
VUE组件自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用
$on(eventName)监听事件 - 使用
$emit(eventName)触发事件
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
<div id="app"><div id="counter-event-example"><p>{{ total }}</p><button-counter v-on:increment="incrementTotal"></button-counter><button-counter v-on:increment="incrementTotal"></button-counter></div></div><script>Vue.component('button-counter', {template: '<button v-on:click="incrementHandler">{{ counter }}</button>',data: function () { // data 必须是一个函数,data 是一个对象则会影响到其他实例return {counter: 0}},methods: {incrementHandler: function () {this.counter += 1this.$emit('increment')}},})new Vue({el: '#counter-event-example',data: {total: 0},methods: {incrementTotal: function () {this.total += 1}}})</script>
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
<my-component v-on:click.native="doTheThing"></my-component>
.sync
感觉这玩意违反单向数据流,数据流向自顶向下
// 父组件<component value.sync="value" />// 子组件改变父组件的值this.$emit('update:title', newValue)
vue-router
this.$router.push({path: "/urlpath",query: {a: 1,b: 2},params: {id: 1}})this.$route.params
