1、基于MV*模式的框架
(1)Model绑定View
(2)没有控制器
(3)数据驱动,状态管理
2、核心思想
(1)数据驱动:非直接操作节点,是通过变量绑定数据
(2)组件化:抽离公用的代码,形成一个个组件
通过MVVM的数据绑定实现自动同步
(3)模拟双向绑定
<input type="text" name="" id="username" /> <span id="uName"></span> <script type="text/javascript"> var obj = {}; // 三个参数:1、对象名 2、对象的要定义或修改属性 3、对定义或修改的属性描述 Object.defineProperty(obj, "username", { get: function() { // 获取该对象属性时执行 console.log("get init"); }, set: function(val) { // 设置该对象属性时执行 document.getElementById("uName").innerHTML = val; document.getElementById("username").value = val; } }); document.getElementById("username").addEventListener("keyup", function(event) { obj.username = event.target.value; }); </script>
(4)单文件组件,一个文件由html、js、css组成
<template> 先是template <div id="app"> <img src="./assets/logo.png"> <router-view/> </div> </template> <script> 这里是js export default { name: 'App' } </script> <style> 最后是css, 若写成<style scoped>是确认当前作用域,不会污染别的文件 #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>
3、安装
这里使用npm安装(使用git-bash命令行)
(1)安装node.js
(2)npm官方镜像比较慢,这里使用淘宝NPM镜像
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
(3)安装vue
$ cnpm install vue
(4)全局安装vue-cli
· 成熟的vue项目架构设计
· 本地测试服务器
· 集成打包上线方案
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo
$ cnpm install -g vue-cli 安装vue-cli
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo
$ vue init webpack mall 初始化项目
? Project name (mall) mall
? Project name mall
? Project description (A Vue.js project) mall system
? Project description mall system
? Author snow-small
? Author snow-small
? Vue build standalone
? Install vue-router? (Y/n) Y
? Install vue-router? Yes
? Use ESLint to lint your code? (Y/n) n
? Use ESLint to lint your code? No
? Set up unit tests (Y/n) n
? Set up unit tests No
? Setup e2e tests with Nightwatch? (Y/n) n
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (reco
? Should we run `npm install` for you after the project has been created? (reco
mmended) no
vue-cli · Generated "mall".
# Project initialization finished!
# ========================
To get started:
cd mall
npm install (or if using yarn: yarn)
npm run dev
Documentation can be found at https://vuejs-templates.github.io/webpack
(5)进入项目,安装依赖
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo $ cd ./mall lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo/mall $ cnpm install
(6)运行
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo/mall
$ cnpm run dev 在localhost启动测试服务器
$ cnpm run build 生成上线目录(部署)
(7)成功显示
> [email protected] dev E:\workspace\xampp\htdocs\demo\mall > webpack-dev-server --inline --progress --config build/webpack.dev.conf.js 95% emitting DONE Compiled successfully in 3970ms20:07:53 I Your application is running here: http://localhost:8080
4、基础语法
(1)模板语法:
· Mustache语法: {{ msg }}
· Html赋值:v-html = ""
· 绑定属性:v-bind:id = ""
· 使用表达式:{{ ok ? "YES", "NO"}}
· 文本赋值:v-text = ""
· 指令:v-if = ""
· 过滤器:{{ message | caputalize}}和v-bind:id = "rawId|formatId"
(2)Class和Style绑定
v-bind:可以省略成:
· 对象语法:v-bind:class = "{active:isActive, 'text-danger':hasError}"
isActive==true时,显示active
· 数组语法:
<div v-bind:class="activeClass, errorClass"> data: { activeClass: active, errorClass: text-danger }
· style绑定对象语法:v-bind:style="{ color: activeColor, fontSie:fontSize + 'px'}"
<div :style="links"></div> data: { links: { font-size: 12px, color: #fff } }
(3)条件渲染:
· v-if
<a v-if="true"></a>
· v-else
<a v-if="true">aaa</a> if显示的时候,else不显示,
<a v-else>bbb</a>
· v-else-if
· v-show
<a v-show="true"></a> 区别是show是display=block
· v-clock 如果页面刷新太快,未加载出来的地方会同步隐藏相关的代码
(4)vue事件处理器
· v-on:click="greet"或@click="greet"
· v-on:click.stop v-on:click.stop.prevent v-on:click.self v-on:click.once
· v-on:keyup:enter/esc/tab
(5)实例对象
new Vue({ el: '#app', 挂载的对象 template: '<div>{{ fruit }}</div>', 使用的模板 data: { fruit: 'apple' 绑定的数据 } });
(6)组件
· 全局组件
<div id="app"> <my-header></my-header> {{ test }} </div> <script type="text/javascript"> Vue.component('my-header', { template: '<p>this is a my-header(全局组件)</p>' }); new Vue({ el: '#app', data: { test: 'this is a apple' } }); </script>
· 局部组件
<div id="app"> <my-header></my-header> {{ test }} </div> <script type="text/javascript"> var myHeader = { template: '<p>this is a my-header(局部组件)</p>' }; new Vue({ el: '#app', data: { test: 'this is a apple' }, components: { 'my-header': myHeader } }); </script>
当组件名为驼峰时myHeaderAbCd,在<template>里使用的时候:vue1时,要写成<my-header-ab-cd></my-header-ab-cd>,大写要分开;在vue2时,可以写成<myHeaderAbCd></myHeaderAbCd>
· 组件之间的通信
父组件向子组件传递时
<comA number-to-do=11></comA> 父组件,属性大小写不敏感,要用-,值都是string import comA from './components/a' components: { comA: comA } 在./components/a中的实例选项中 子组件要得到父组件的属性,需要使用props,使用时要转成驼峰形式{{ numberToDo }} props: ['number-to-do']
或props: {
'number-to-do': [Number, String] 传对象,支持数字、字符型
}
子组件向父组件传递,通过事件传递
在./components/a中 <button @click="emitMyEvent"></button> methods: { emitMyEvent () { this.$emit('my-event', 'this is components a') 在子组件中触发事件,通过$emit触发父组件中的自定义事件,并传参数 } } 在父组件中 <comA @my-event="getMyEvent"></comA> 父组件中自定义事件,大小写不敏感 methods: { getMyEvent (params) { 参数值为子组件传来的值,== i get a event this is components a console.log('i get a event' + params) } }
父组件向子组件传递模板
在父组件中
<comA>
<p>11111</p><span>2222</span>
</comA>
在子组件中
<slot></slot> 使用<slot></slot>来接收,父组件的模板 == <p>111</p><span>2222</span>
有具名的slot
子组件 <slot name="header">no header</slot> 有具体名称,值默认为no header <slot name="footer">no footer</slot> 父组件 <comA> <p slot="header">xxxx header</p> 使用slot="具体名称"来确认不同的slot <p slot="footer">xxxx footer</p> </comA>
(7)v-for使用
数组:
<div id="app"> <p v-for="item in list">{{ item.name }} - {{ item.price }}</p> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { list: [ { name: 'apple', price: 23 }, { name: 'banana', price: 24 } ] } }); </script>
若是要有序号,在v-for="(item, index) in list",使用时{{ index }}从0开始的序号
对象:
<div id="app"> <p v-for="(value, key) in objList">{{ value }} - {{ key }}</p> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { objList: { name: 'apple', price: 22, weight: 20 } } }); </script>
列表更新:
methods: {
change() {
Vue.set(this.list, 1, { 第一项要改变的列表,第二项第几个数据,三为改变后的值
name: 'orange',
price: 20
})
}
}
(8)表单绑定
<input type="text" v-model="myValue">
<input type="checkbox" v-model="box" value="apple"> 复选框
<input type="checkbox" v-model="box" value="banana">
<input type="checkbox" v-model="box" value="orange">
{{ box }}
data: {
box: []
}
<input type="radio" v-model="box" value="apple"> 单选按钮
<input type="radio" v-model="box" value="banana">
<input type="radio" v-model="box" value="orange">
{{ box }}
<select v-model="section"> <option value="1">1</option> <option value="2">2</option> </select> {{ section }} data: { section: null }
v-model.lazy:延迟
v-model.number:整形
v-model.trim:去空格
(9)计算属性
<div id="app">
<input type="text" v-model="myValue">
{{ inputWithoutNumber }}
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
myValue: '',
},
computed: {
inputWithoutNumber () {
return this.myValue.replace(/\d/g, ''); 去掉数字
}
}
});
</script>
(10)属性监听
<div id="app">
<input type="text" v-model="myValue">
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
myValue: '',
},
watch: {
myValue (newValue, oldValue) { 监听myValue
console.log(newValue, oldValue);
}
}
});
</script>
(11)css3过渡动画
<div id="app"> <button @click="show = !show">toggle</button> <transition name="fade"> 通过transition,name随便取 <p v-show="show">i am show</p> </transition> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { show: true } }); </script> <style type="text/css"> .fade-enter-active, .fade-leave-active { v-enter...中的v是上面的name transition: opacity .5s; } .fade.enter, .fade-leave-active { opacity: 0; } </style>
对于多元素动画,<transition mode="out-in">模式是先出后进,默认先进后出,
若多元素标签相同,如<p key="1">i am one</p> <p key="2">i am two</p>,实现一个进一个出,不加key区别的话,不会有动画
(12)js实现动画
<div id="app"> <button @click="show = !show">toggle</button> <transition @before-enter="beforeEnter" @enter="enter" @leave="leave" :css="false" > 清除css的影响 <p class="animate-p" v-show="show">i am show</p> </transition> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { show: true }, methods: { beforeEnter (el) { $(el).css({ left: '-500px', opacity: 0 }) }, enter (el, done) { $(el).animate({ left: 0, opacity: 1 }, { duration: 1500, complete: done 一定要有done }) }, leave (el, done) { $(el).animate({ left: '500px', opacity: 0 }, { duration: 1500, complete: done }) } } }); </script> <style type="text/css"> .animate-p { position: absolute; left: 0; } </style>
(13)自定义指令
<div id="app"> <p v-color="'red'">this is v-color</p> v-color是自定义指令 </div> <script type="text/javascript"> new Vue({ el: '#app', directives: { 定义 color (el, binding) { 当前的元素,绑定的值 el.style.color = binding.value } } }); </script>