插值表达式, 从data中获取数据展示
示例
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }}注意: 网速慢 ,会出现插值闪烁的问题
<!--v-cloak 解决闪烁问题--> <style> [v-cloak] { display: none; } </style> <div id="vue" v-cloak></div>绑定属性 , 将data中的数据与html标签的属性绑定 , 可缩写 为 :属性名
示例
<div v-bind:class="{ active: isActive }"></div> <div class="static" :class="{ active: isActive, 'text-danger': hasError }"></div>绑定事件 , 将标签元素的事件与函数绑定 , 可缩写 为 @事件名
示例
<button v-on:click="num++">点我</button> <input @keyup.enter="a(3)"/>循环遍历 , 遍历数组 或 对象
示例
<!--遍历数组--> <li v-for="(item,index) in items" :key="index"> {{item}} </li> <!--遍历对象--> <li v-for="(value, key, index) in user" :key="index"> {{index + 1}}. {{key}} - {{value}} </li>过滤
可以使用filter函数过滤
items.filter(p=>{
if ( p . indexof (this.keywords) !=-1 return true;
})
排序
使用sort排序
persons.sort( function( p1 , p2){
if(orderType==1) return p1.age-p2.age;
if(orderType==2) return p2.age-p1.age;
} )
查找
使用find
persons.find(person=>{
if(person.name=‘zzhua’)
})
双向绑定 , 一般在表单元素中使用双向数据绑定
示例
输入框
input:<input type="text" v-model="message"> {{message}}文本域
<textarea v-model="message"></textarea>单选框
<input type="radio" id="male" value="Male" v-model="gender"> Male <input type="radio" id="female" value="Female" v-model="gender"> Female <p>{{gender}}</p> data: { gender:'Male' }复选框
<input type="checkbox" value="ps" v-model="hobbies"> <input type="checkbox" value="blender" v-model="hobbies"> {{hobbies}} data: { hobbies:['blender'] }下拉框:
<select v-model="score" name="score"> <option disabled value="">请选择</option> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> </select> data: { score:'A' }控制元素的显示和隐藏,v-if若为false,元素则不会被渲染出来
示例
<h1 v-if="random >= 0.75"> 内容 </h1> data: { random: 1 }如果要用v-else,须紧跟v-if才能用
控制元素的显示和隐藏, 通过控制元素的display属性,display : none
示例
<h1 v-if="show"> 你好 </h1> data:{ show:true }只要定义,全局都可以使用
示例
Vue.component("counter",{ template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>', data(){ return { count:10 } } })需要注册给vue实例,才能使用
示例
<!-- 1. 定义 --> const mycounter = { template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>', data(){ return { count:10 } } } <!-- 2.注册 --> var app = new Vue({ el:"#app", components:{ 'my-counter':mycounter } }) <!-- 3.使用 --> <my-counter></my-counter>通过 子组件的自定义属性传值 props : [ ’ prop1 ’ , ’ prop2 ’ , …]
示例
<div id="app"> <mycomp :item= "hobby" ></mycomp> <input v-model="hobby"/> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> const mycomp = { props: ['item'], template: ' <li> {{ item }} </li> ' } var vm = new Vue({ el:"#app", data: { hobby: ' blender ' }, components:{ mycomp // 局部组件,需要注册 } }); </script>注意事项
子组件不能直接修改通过props传过来的值,修改会报错。 因为一旦父组件修改了这个属性的值的话, 那么这个值会重新渲染给子组件,那么子组件修改这个值毫无意义props可以传递父组件的函数
子组件定义 props:{addComment:Function},接收函数,直接调用非直接子组件需要逐层传递,后代组件才可以待用兄弟组件不能直接props通信,必须借助父组件才可以【理解:props就是子组件从父组件那里拿东西的地方,既可以拿数据,又可以拿函数,
但前提是父组件要传递给它才可以用】
通过 子组件的自定义事件,调用vue实例中的方法
示例
<div id="app"> <h2>num: {{num}}</h2> <counter :count="num" @inc="increment(1)" @dec="decrement(1)"> </counter> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> Vue.component("counter", { template: '\ <div>\ <button @click="plus">加</button> \ <button @click="reduce">减</button> \ </div>', props: ['count'], methods: { plus() { this.$emit("inc", 10); }, reduce() { this.$emit("dec", 10); } } }); var app = new Vue({ el: "#app", data: { num: 0 }, methods: { // 父组件中定义操作num的方法 increment(x) { this.num = this.num + x; }, decrement(x) { this.num = this.num - x; } } }) </script>注意点
inc和dec相当于是 组件的自定义事件 ,这个事件绑定了 vue实例中的方法, 同其它dom元素一样,当发生这个事件的时候,就会触发这个绑定的方法。子组件内通过 this .$emit( ’ 事件名 ',参数1,参数2 …) ,自己主动触发指定事件,所以vue实例中的方法就被调用了如果子组件在使用时自定义的事件绑定的方法中如果有参数的话,那么参数始终以绑定的方法中的参数为准; 如果没有参数,那么才用$emit后面跟的参数[总结]
你要么是通过在子组件中的props中定义属性或函数来接收父组件的属性或函数,然后在子组件中用。
要么是通过在子组件使用时,给子组件自定义事件,然后在子组件调用子组件自己的方法的时候,触发自定义事件,从而调用父组件的方法
安装 npm install --save pubsub-js
双方引入 import PubSub from ‘pubsub-js’
以删除为例
发布消息
PubSub.publish("del",index)订阅消息
mounted() { PubSub.subscribe("del",(msg, index)=> { this.delItem(index) // this代表组件 }) }订阅发布可以父与后代通信,兄弟组件之间通信
在computed中所有出现过的data数据,只要有一个发生变化,都会重新计算值,渲染到页面中
示例
<div id="vue"> a: {{ a }} <br/> b: {{ b }} <br/> c: {{ c }} <br/> a:<input v-model="a"/> b:<input v-model="b"/> 全选: <input type="checkbox" v-model="isAllchecked" /> {{falg}} </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vue', data: { a: 1, b: 2, flag:true }, computed: { c() { this.b; // 当b发生变化时,此函数就被调用,c就变化 return new Date(); }, isAllChecked:{ set:function(value){ alert("isAllChecked该改变被触发"); this.flag=isAllChecked; }, get:function(){ return this.flag; } } } }); </script>监听某个变量 , 当它发生变化时, 触发方法
示例
<div id="demo"> {{num}} <input v-model="num"> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#demo', data: { num:0 }, watch: { num:function (newVal,oldVal ) { alert("上次的值:" + oldVal + ",更新为: " + newVal) } } }) </script>深度监视
watch:{
items:{
deep:true, // 开启深度监视
handler:function(value){
window.localStorage.setItem(“items”,value);
}
}
}
取值:JSON.parse(window.localStorage.getItem(“item”)||’[]’);
使用
组件中定义插槽 ,作为后期插入组件的占位符。
后期组件通过slot=“插槽名”,指定要插入的位置
<div id="vue"> <todo> <todo-title slot="todo-title" title="软件"></todo-title> <todo-items slot="todo-items" v-for="(item, index) in todoItems" v-bind:item="item" v-bind:index="index" :key="index"></todo-items> </todo> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('todo', { template: '<div>\ <slot name="todo-title"></slot>\ <ul>\ <slot name="todo-items"></slot>\ </ul>\ </div>' }); Vue.component('todo-title', { props: ['title'], template: '<div>{{title}}</div>' }); //这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来! Vue.component('todo-items', { props: ['item', 'index'], template: '<li>{{index + 1}}. {{item}}</li>' }); var vm = new Vue({ el: '#vue', data: { todoItems: ['blender', 'ps', 'java'] } }); </script>Vue提供的操作dom元素 的方式
在标签元素中标记 ref , 在vue实例中即可访问该元素示例
<div id="vue"> <input ref="r1" value="zzhua"> <button @click="invoke()">弹出来</button> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> var mycount = {template: '<div></div>',} var vm = new Vue({ el: '#vue', data: {}, methods:{ invoke(){ console.log(this) alert(this.$refs.r1.value) } }, components:{ mycount } }); </script>绑定监听
无参数时默认:隐含属性对象: $event ,
函数可以接收这个对象, 通过event.target.value 拿到dom的value
<button @click=“test01()”>有参数时须指定$event:
<button @click="test02( ‘hello’ , $event ) ">事件修饰符
.prevent : 阻止事件的默认行为 event.preventDefault()
<!-- 阻止事件默认行为 --> <a href="http://www.baidu.com" @click.prevent="test3">百度一下</a>.stop : 停止事件冒泡 event.stopPropagation()
<!-- 停止事件冒泡 --> <div style="width: 200px;height: 200px;background: red" @click="test4"> <div style="width: 100px;height: 100px;background: green" @click.stop="test5"> </div>按键修饰符
@keyup 按任意键触发 <input @keyup=“test6”>$event.keyCode可以查看按的键 <input @keyup.enter=“test6”> 按enter键时触发1.安装nodejs
http://nodejs.cn/download/
检查安装是否成功
node -v
npm -v
npm是软件包管理工具,nodejs自带npm nodejs安装会默认配置好环境变量
3.安装镜像
npm install cnpm -g 安装镜像加速npm install nrm -g 镜像切换工具nrm ls 查看npm的仓库列表nrm use taobao 指定要使用的镜像源npm install -g cnpm --registry=https://registry.npm.taobao.org 安装淘宝镜像 cnpm命令npm install
检查并安装所有依赖npm install moduleName
安装模块到项目目录下npm install -g moduleName
-g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置npm install -save moduleName:
–save 的意思是将模块安装到项目目录下,并在 package 文件的 dependencies 节点写入依赖,-S 为该命令的缩写npm install -save-dev moduleName
–save-dev 的意思是将模块安装到项目目录下,并在 package 文件的 devDependencies 节点写入依赖,-D 为该命令的缩写注意点
g 为全局安装,安装位置:C:\Users\Administrator\AppData\Roaming\npmsave - dev 安装到项目目录 WebPack 是一款模块加载器兼打包工具, https://www.jianshu.com/p/42e11515c10f 使用步骤 安装 npm install webpack -g npm install webpack-cli -g 测试安装成功 webpack -v webpack-cli -v
创建一个基于 webpack 模板的 vue 应用程序
vue init webpack 项目名运行
cd myvue 切换到项目根目录下npm install 安装所有需要的依赖npm run dev 运行脚本,启动项目, 即可访问build 和 config WebPack 配置文件
node_modules 用于存放 npm install 安装的依赖文件
src 项目源码目录
static 静态资源文件
.babelrc: Babel 配置文件,主要作用是将 ES6 转换为 ES5
.editorconfig: 编辑器配置
eslintignore: 需要忽略的语法检查配置文件
.gitignore: git 忽略的配置文件
.postcssrc.js: css 相关配置文件,其中内部的 module.exports 是 NodeJS 模块化语法
index.html: 首页,仅作为模板页,实际开发时不使用
package.json: 项目的配置文件
name:项目名称version:项目版本description:项目描述author:项目作者scripts:封装常用命令dependencies:生产环境依赖devDependencies:开发环境依赖引入组件
映射成标签
使用组件标签
定义组件模板 <template> <div> <p class="msg">{{msg}}</p> </div> </template> <script> export default { data(){ return { msg:"学会Vue" } } } </script> <style> .msg{ color: red; } </style> App.vue <template> <div> <img src="./assets/logo.png" alt="找不到图片"> <hello-world/> <!--第三步:使用组件--> </div> </template> <script> import HelloWorld from './components/HelloWorld' <!--第一步:引入组件--> export default { components:{ HelloWorld <!--第二步:映射成标签--> } } </script> <style> </style>main.js
webpack构建项目,在webpack.base.conf.js指明了main.js为入口文件
main.js相当于就是script标签里的内容,控制index.html页面
template会取代index.html页面的挂载位置
import Vue from 'vue' <!--相当于导入vue.js--> import App from './App' <!--第一步:引入组件--> new Vue({ el:'#app', <!--设置挂载点--> components:{ App <!--第二步:映射成标签--> }, template:'<App/>' <!--第三步:使用组件--> }); index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>vue-demo</title> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html> 整个就相当于单页面的 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="vue"> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> const mycounter = { template: '<div>我是要学好vue的人</div>' } var vm = new Vue({ el: '#vue', data: { }, methods: {}, components:{ aaa:mycounter }, template: '<aaa/>' }); </script> </body>5.打包发布
npm run build
会生成dist文件夹,dist即为最终项目npm serve
即可运行前提条件是:安装了静态服务器工具包 ,使用命令: npm install -g serve安装
npm install --save axios vue-axiosmain.js中引入
import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)使用
#执行 GET 请求 // 为给定 ID 的 user 创建请求 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); # GET 请求也可以这样做 axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); #执行 POST 请求 axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); # 发送 POST 请求 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); # 获取远端图片 axios({ method:'get', url:'http://bit.ly/2mTM3nY', responseType:'stream' }) .then(function(response) { response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) }); #为方便起见,为所有支持的请求方法提供了别名 axios.request(config) axios.get(url[, config]) axios.delete(url[, config]) axios.head(url[, config]) axios.options(url[, config]) axios.post(url[, data[, config]]) axios.put(url[, data[, config]]) axios.patch(url[, data[, config]]) #更多用法 http://www.axios-js.com/zh-cn/docs/index.html #springmvc接口跨域配置 <!-- API 接口跨域配置 --> <mvc:cors> <mvc:mapping path="/api/**" allowed-origins="http://d.demo.com:8080" allowed-methods="POST, GET, OPTIONS, DELETE, PUT" allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With" allow-credentials="true" /> </mvc:cors> #springboot跨域配置 //单个配置 @CrossOrigin(origins = {"http://localhost:9000", "null"}) @RestController @SpringBootApplication public class SpringBootCorsTestApplication { } //全局配置 @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowCredentials(true); } } #或者 @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:9000"); config.addAllowedOrigin("null"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效 FilterRegistrationBean bean = newFilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; }App.vue
<template> <div class="container"> <search/> <Content/> </div> </template> <script> import Content from './components/Content' import Search from './components/Search' export default { components:{ Content, Search } } </script> <style> </style>Conten.vue
<template> <div class="row"> <div v-if="!isSearching"> <h3>请输入关键词搜索</h3> </div> <div v-if="isLoading"> <h3>LOADING.............</h3> </div> <div v-if="isError"> <h3>出错了啦,请重试哦亲~</h3> </div> <div class="card" v-if="user" v-for="(user,index) in users" :key="index"> <a :href="user.url" target="_blank"> <img :src="user.avatar_url" style='width: 100px'/> </a> <p class="card-text">{{user.name}}</p> </div> </div> </template> <script> import PubSub from 'pubsub-js' import axios from 'axios' export default { data() { return { isSearching: false, isLoading: false, isError:false, users: null // [{url:'',avatar_url:'',name:''}] } }, mounted() { PubSub.subscribe("search", (msg, keywords) => { this.isError=false const {isSearching,isLoading,users} = this; this.isSearching=true; this.isLoading=true; this.users=null; axios.get(`https://api.github.com/search/users?q=`+keywords).then(response=> { this.isLoading = false; const data = response.data; this.users = data.items.map(item => ({ url: item.url, avatar_url: item.avatar_url, name:item.login })); }).catch(error=>{ this.isLoading = false; this.isError=true }) }) } } </script> <style> </style>Search.vue
<template> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" v-model="keywords" placeholder="enter the name you search"/> <button @click="doSearch">Search</button> </div> </section> </template> <script> import PubSub from 'pubsub-js' export default { data(){ return { keywords:'' } }, methods:{ doSearch(){ PubSub.publish("search",this.keywords) } } } </script> <style> </style>main.js
import Vue from 'vue' import App from './App' new Vue({ el:'#app', components:{ App }, template:'<App/>' });src下新建router文件夹,新建名为index.js
import Vue from 'vue' // 导入Vue import Router from 'vue-router' // 导入路由插件 Vue.use(Router); // 安装路由 import content from '../components/Home' // 导入需要路由的组件 import main from '../components/Main' export default new Router({ // 配置路由 routes: [ {path: '/home',component: Home}, {path: '/about',component: About} ] });main.js中配置路由
import Vue from 'vue' import App from './App' import router from './router' // 导入上面创建的路由配置目录,index.js可默认省略 new Vue({ el: '#app', components: { App }, template: '<App/>', router //配置路由 })App.vue中使用路由
<template> <div id="app"> <router-link to="/content"></router-link> <router-link to="/main"></router-link> <keep-alive> <router-view></router-view> </keep-alive> </div> </template> <script> export default { components: { } } </script> <style> ... </style>1.前提
index.html被main.js控制,main.js会用App.vue中的代码替换index.html中的id="app"的div。所以代码最终都是要控制在App.vue中。main.js中给vue实例注册了路由2.过程
当路由发生变化时,根据main.js给App.vue绑定的路由router来控制。
router中有定义路由跳转规则的routes
routes定义的最外层路由(非子路由),才会被填充到App.vue。
结论
如果匹配到的是最外层路由,那么最外层路由匹配到的组件会被直接渲染到App.vue中
的位置
如果匹配到的是子路由,那么顺着子路由一直到最外层路由,将对应的最外层路由渲染到App.vue中
的位置,然后子路由在最外层路由对应组件的中的位置渲染
1.声明式导航
组件在template中使用导航1
参数会被封装在$route.query.id传递多个参数 导航2动态传参
children: [ { path:'/home/msg/:id', // 路由占位符 ,参数会被封装在$route.params.id component:MessageDetail } ] <ul> <li v-for="(msg,index) in msgs" :key="index"> <!--路由参数,动态传递--> <router-link :to="`/home/msg/${msg.id}`"> {{msg.id}}--{{msg.name}}</router-link> <!--另一种写法--> <router-link :to="'/home/msg/'+msg.id"> {{msg.id}}--{{msg.name}}</router-link> </li> </ul> <!--取出参数--> {{$route.params.id}} <!--监视路由--> watch:{ $route:function(value){ value.params.id ; // 获取路由变化后的参数id值 } }2.编程式导航
this . $router .push (‘路径’)
this . $router .push ({ path:‘路径’ , query : { id: 1} }) // 携带参数this . $router .replace(‘路径’)
替换当前路由this . $router .back( )
返回3.路由参数
$router 路由器参数 $router.options.routes // 获取所有路由数据 $route 当前路由参数 $route.path$route.query$route.params3.scope属性
stylede 的scope属性:如果加上,那么切换到该组件时,只被应用到该组件;如果没加,将应用到整个页面;
安装sass加载器
npm install sass-loader node-sass --save-dev