前端笔记之Vue(五)TodoList实战拆分store跨域练习代理跨域
一、TodoList
1.1安装依赖
安装相关依赖:
npm install --save-dev webpack npm install --save-dev babel-loader babel-core babel-preset-es2015 npm install --save-dev vue-loader npm install --save-dev css-loader npm install --save-dev vue-template-compiler npm install --save-dev stylus stylus-loader npm install --save vue npm install --save vuex
1.2配置虚拟服务器
【第一步:安装依赖】
npm install -g json-server
【第二步:json-server的服务器启动】
启动需要json文件作为支撑,新建data.json文件做服务数据:
{"mapList" : [{"id":1 ,"title" : "吃饭", "done" : false},{"id":2 ,"title" : "睡觉", "done" : false},{"id":3 ,"title" : "做饭", "done" : false},{"id":4 ,"title" : "扫地", "done" : false}] }
启动命令json-server命令: json-server 数据文件路径 -s 静态化目录 -p 8080json-server www/data/data.json -s ./www -p 8080 -s是 --static -p是 --port
最终没有使用webpack-dev-server模拟服务器
配置webpack.config.js文件:
const path = require('path'); const {VueLoaderPlugin} = require('vue-loader'); //最新版webpack需要引入插件 module.exports = {//程序的入口文件entry: "./www/app/app.js",//程序的出口(打包的文件) output : {//打包文件输出的路径path : path.resolve(__dirname, "www/dist"),//打包文件的名称filename : "all.js",// publicPath:"/public" //这是对webpack-dev-server的配置,配置虚拟路径 },//让webpack监听变化,自动打包watch : true,mode : "development",//配置webpack的模块插件 module:{//关于模块的配置规则 rules : [{//模块规则(配置 loader、解析器等选项)test : /\.js$/, //解析的时候匹配到的都是js文件 include: [path.resolve(__dirname, "www/app") //翻译什么文件夹 ],exclude: [path.resolve(__dirname, "node_modules") //不翻译什么文件夹 ],loader : "babel-loader", options : {presets : ["es2015"]}},{test: /\.vue$/,include: [path.resolve(__dirname, "www/app") //翻译什么文件夹 ],exclude: [path.resolve(__dirname, "node_modules") //不翻译什么文件夹 ],loader: 'vue-loader',options :{loaders : {stylus:'vue-style-loader!css-loader!stylus-loader'}}},{test:/\.css$/,use: ['vue-style-loader','css-loader']}// {// test: /\.styl(us)?$/,// use: [// 'vue-style-loader',// 'css-loader',// 'stylus-loader'// ]// } ]},resolve: {alias: { //配置别名'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js' }},//最新版webpack需要引入插件 plugins : [new VueLoaderPlugin()] }
【第三步:访问接口】
获取所有的数据:GET
增加数据:POST
得到某一条数据:GET
删除某一条:DELETE
更新原始数据:PUT (更新条目的所有的属性)、PATH(更新条目的某一个属性)
自带分页:page(第几页)limit(每页有多少条)
http://localhost:8080/mapList 返回.json文件所有数据(数组) http://localhost:8080/mapList/1 返回id=1的数据,采用这种路径风格id必须为小写(数组) http://localhost:8080/mapList/?Name=lst 返回Name=lst的用户数据(数组)
分页查询:参数为 _start, _end, _limit,并可添加其它参数筛选条件,如: http://localhost:8080/mapList?_start=6&_limit=3 http://localhost:8080/mapList?_start=3&_end=6 排序:参数为_sort, _order http://localhost:8080/mapList?_sort=id&_order=asc http://localhost:8080/mapList?_sort=user,views&_order=desc,asc 操作符:_gte, _lte, _ne, _like _gte大于,_lte小于, _ne非, _like模糊查询,q关键词查询 http://127.0.0.1:8080/mapList/?q=吃
1.3 TodoList
查询数据
相关步骤:
在created生命周期中发出一个GETALL的异步命令,去actions里面发异步请求。
App.vue
<script>export default {created(){this.$store.dispatch("GETALL");}} </script>
main.js
import Vue from "vue"; import Vuex from "vuex"; import App from "./App.vue"; Vue.use(Vuex);const store = new Vuex.Store({ state : {todos : []},mutations: {GETALL(state,payload){// state.todos.push(payload)state.todos = payload;}},actions :{async GETALL({commit}){//请求数据库中的数据,然后存储到state的todos中var data = await fetch("/maplist").then(data=>data.json());//发出commit()命令,并且将参数当载荷传递过去commit("GETALL", data);}} });new Vue({el : "#app",store,render:(h)=>h(App) })
异步请的数据回调成功后,将数据以载荷的形式发送到mutations,再去修改state 的数据
state全局仓库有了数据,就可以在App.vue进行循环渲染。
App.vue
<template><div><ul><li v-for="item in todos">{{item.title}}</li></ul></div> </template> <script>export default {created(){this.$store.dispatch("GETALL");},computed : {todos(){return this.$store.state.todos}}} </script>
下一步:需要将li标签拆分成组件:
App.vue
<template><div><ul><li is="TodoLi" v-for="item in todos" :item="item"></li></ul></div> </template> <script>import TodoLi from "./components/TodoLi.vue";export default {created(){this.$store.dispatch("GETALL");},computed : {todos(){return this.$store.state.todos}},components:{ TodoLi}} </script>
TodoLi.vue
<template><li>{{item.title}}</li> </template> <script>export default {props : ["item"]} </script>
删除数据
接下来写增删改查业务,推荐先写删除,因为删除值需要id
TodoLi.vue
<template><li><span>{{item.title}}</span><button @click="del(item.id)">删除</button></li> </template> <script>export default {props : ["item"],methods:{del(id){this.$store.dispatch("DEL", {id})}}} </script>
const store = new Vuex.Store({state : {todos : []},mutations: {GETALL(state,payload){// state.todos.push(payload)state.todos = payload;},DEL(state, payload){// 根据id删除state的数据state.todos = state.todos.filter(item=>{return item.id != payload.id;})}},actions :{async GETALL({commit}){//请求数据库中的数据,然后存储到state的todos中var data = await fetch("/maplist").then(data=>data.json());//发出commit()命令,并且将参数当载荷传递过去commit("GETALL", data);},async DEL({commit},payload){//向服务器发出删除请求,删除data.json中的数据var data = await fetch("/maplist/" + payload.id, {method:"DELETE",}).then(data => data.json());commit("DEL", payload); //删除全局state仓库的数据 },} });
新增业务
App.vue
<template><div><div><input type="text" v-model.trim="txt"><button @click="add">新增</button></div><ul><li is="TodoLi" v-for="item in todos" :item="item"></li></ul></div> </template> <script>import TodoLi from "./components/TodoLi.vue";export default {data(){return { txt : ''}},methods :{add(){if(this.txt == '') return;//发出新增的异步请求this.$store.dispatch(ADD, {id: new Date() - 0, title:this.txt, done:false})this.txt = ""}},components:{TodoLi}} </script>
main.js
actions : {//新增数据 async ADD({ commit }, payload) {//向data.json文件中插入数据 var data = await fetch("/maplist/", {method: "POST",headers:{'Content-type' : 'application/json'},body: JSON.stringify(payload)}).then(data => data.json());commit("ADD", data); //新增数据到state,影响视图更新 } }, mutations : { ADD(state, payload) {state.todos.push(payload);} }
修改数据
TodoLi.vue
<template><li> <span v-if="!isShow" @dblclick="showInput">{{item.title}}</span><input type="text" v-if="isShow" v-model="item.title" @blur="hideInput(item)" v-focus><button @click="del(item.id)">删除</button></li> </template> <script>export default {props : ["item"],data(){return{isShow:false}},methods:{del(id){this.$store.dispatch("DEL", {id})}, showInput(){//双击显示inputthis.isShow = !this.isShow;},hideInput(item){console.log(item)//失去焦点隐藏input,并且发送CAHNGETITLE命令修改title内容this.isShow = !this.isShow;this.$store.dispatch("CHANGETITLE",item)}}, directives:{//自定义组件指令,自动获取焦点 focus :{inserted(el){el.focus();}}}} </script>
main.js
const store = new Vuex.Store({state : {todos : []},mutations: {CHANGETITLE(state, payload) {// 写法1// state.todos.forEach(item=>{// if (item.id == payload.id){// item.title = payload.title;// }// })// 写法2state.todos = state.todos.map(item => {if(item.id == payload.id) {return payload}return item;})}},actions :{//修改请求 async CHANGETITLE({commit}, payload) {var data = await fetch("/maplist/" + payload.id, {method: "PATCH",headers: { 'Content-Type': 'application/json' },body: JSON.stringify(payload)}).then(data => data.json());commit("CHANGETITLE", data); //虽然实现了修改,但是为了完整性还是写上 },} });
修改任务事件:当前任务是否做了,需要一个复选框
todoli.vue
<li> <input type="checkbox" v-model="item.done" ref="cbox" @click="changeDone(item)"> <spanv-if="!isShowInput"@dblclick="showInput" :class="{cur:item.done}">{{item.title}}</span> </li> <script> methods:{ changeDone(item){console.log(this.$refs.cbox.checked);// 这里使用的是ref钩子 这样能得到 复选框的状态 // 提交的时候 只需要提交 id 复选框的状态就行了this.$store.dispatch("CHANGEDONE",{id : item.id,done : this.$refs.cbox.checked}) } } </script> <style>.cur{text-decoration: line-through;} </style>
app.js修改done和修改title的方式方法都一样,只要改方法名即可。
const store = new Vuex.Store({mutations:{CHANGEDONE(state, payload){state.todos = state.todos.map(item => {if(item.id == payload.id){return payload}return item})} }, actions:{async CHANGEDONE({commit},payload){var data = await fetch("/mapList/" + payload.id,{"method" : 'PATCH',"headers":{'Content-Type':"application/json"},body:JSON.stringify({done:payload.done})}).then(res => res.json()); commit("CHANGEDONE",data)}, } });
筛选按钮:计算已做未做事项
筛选按钮:计算已做未做事项
app.js
const store = new Vuex.Store({state:{todos:[]},mutations:{...},actions:{...},getters:{yizuo:function(state){return state.todos.filter(item => {return item.done == true //true表示已做})},weizuo:function(state){return state.todos.filter(item => {return item.done == false //false表示未做 })}} });
App.vue
<template><div><div><input type="text" v-model.trim="txt"><button @click="add">新增</button></div><ul><li v-for="item of todos" is="TodoLi" :item="item"></li></ul><div>全部:{{$store.state.todos.length}}个事项<br>已做:{{$store.getters.yizuo.length}}个完成事项<br>未做:{{$store.getters.weizuo.length}}个代办事项<br></div><div><button @click="all">查看全部</button><button @click="yizuo">查看已做</button><button @click="weizuo">查看未做</button></div></div> </template> <script> import todoli from './components/TodoLi.vue' export default {data() {return {txt: '',state: 'all'}},computed: { todos() {if(this.state == 'all'){return this.$store.state.todos}else if(this.state == 'yizuo'){return this.$store.getters.yizuo}else if(this.state == 'weizuo'){return this.$store.getters.weizuo}}},methods: { all() {this.state = 'all'},yizuo() {this.state = 'yizuo'},weizuo() {this.state = 'weizuo'}} } </script>
所有业务都已经完成,但是由于组件和数据太乱,下面开始拆分store。
二、拆分store
我们都知道vuex是vue用来集中管理状态的容器(管理全局的状态),实现不同组件之间相互的数据访问。我们说一下vuex拆分store以及多模块管理。如果一个项目非常大的话状态就会非常的多,如果不进行分类处理,所有的状态都维护在一个state里面的话,状态管理就会变得非常的混乱,这样非常不利于项目的后期维护。现在前端推崇模块化开发,为的就是提高开发效率和维护效率,避免重复工作。那么vuex是怎么样解决这个问题的呢?这个时候我们今天要讲的主角modules就要闪亮登场了。
第一步:将main.js中的store拆分到一个js文件中。
export const storeObj = {state:{...},mutations:{...},actions:{...},getters:{...} }
将store中的index.js在main.js中引入
import {storeObj} from "./store/index.js"; const store = new Vuex.Store(storeObj);
第二步:拆分state、mutations、actions、getters
给他们分别创建单独的js文件,默认暴露
export default {}
可以将我们定义的这些对象加入到Vuex的store中
在store中index.js用import引入:
import state from "./state.js"; import mutations from "./mutations.js"; import actions from "./actions.js"; import getters from "./getters.js";export const storeObj = {state:{...state},mutations:{...mutations},actions:{...actions},getters:{...getters} }
示例代码
由于没装翻译“...”对象解构语法,会报错:
npm install --svae-dev babel-plugin-transform-object-rest-spread
配置webpack.config.js
{test: /\.js?$/, //解析的时候匹配到的都是jsloader: "babel-loader",//翻译字典 options: {presets: ["es2015","ES2015"], plugins: ["transform-object-rest-spread"]} },
配置完成后就可以识别“...”解构了。
至此,还没拆完,使用常量代替mutations集合actions的type名字
新建一个types.js文件,在里面存常量(大写字母的方法)
注意:把这些常量放到单独的文件中可以让你的代码合作者对整个app包含mutation和actions一目了然。
用不用常量代替取决于你--在需要多人协作的大型项目中,这会很有帮助,但是如果你不喜欢,完全可以不这么做。
export const GETALL = "GETALL"; export const DEL = "DEL"; export const ADD = "ADD"; export const CHANGETITLE = "CHANGETITLE"; export const CHANGEDONE = "CHANGEDONE";
暴露常量的名字后,分别在mutations和actions的js文件中使用这些来代替:
mutations.js
import {GETALL,DEL,ADD,CHANGETITLE,CHANGEDONE} from "./types.js"; export default {[GETALL](state, payload) {}, [DEL](state, payload) {},[ADD](state, payload) {},[CHANGETITLE](state, payload) {},[CHANGEDONE](state, payload) {} }
actions.js
import {GETALL,DEL,ADD,CHANGETITLE,CHANGEDONE} from "./types.js"; export default {async [GETALL]({ commit }) {}, async [DEL]({ commit }, payload) {},async [ADD]({ commit }, payload) {}, async [CHANGETITLE]({ commit }, payload) {},async [CHANGEDONE]({ commit }, payload) {} }
注意:上方mutations和actions中的[types.ADD]写法,因为types.ADD是一个对象,所以不能直接当做函数名来写,需要用到ES2015风格的计算属性命名功能来使用一个常量作为函数名,才能使用。
https://vuex.vuejs.org/zh/guide/mutations.html
三、异步请求数据(跨域)
3.1 Ajax不能跨域
比如在Apache中演示:
<html> <head><title>Document</title> </head> <body><script src="jquery-3.3.1.min.js"></script><script>$.get("http://127.0.0.88/a.txt" , function(data){console.log(data);});</script> </body> </html>
试图在127.0.0.1请求127.0.0.88/a.txt的JSON数据,会报错:
浏览器会阻止对ip地址不同,或者端口号不同的数据请求。
此时我们必须要进行请求,就是跨域技术。
3.2用jQuery复习JSONP跨域
<html> <head><title>Document</title> </head> <body><script> function haha(info){console.log(info);}</script><script src="http://127.0.0.88/a.txt"></script> </body> </html>
在页面上定义一个函数,然后用script标签引入这个语句,执行这个语句。此时数据就通过函数的实参和形参的结合,传入了页面。script没有跨域限制的,可以轻松src引入其他ip地址的js文件。
JSONP叫做JSON 和 Padding(补白)
我们写一个接口,这个接口不是一个JSON,而是一个语句,这个语句是函数的调用。
升级:把a.txt改为a.php(这个文件不需要会,因为是后端的事情)
<?php $callback = $_GET["callback"]; //获取get请求 echo $callback . '({"a" : 100 })';//JSON参数 ?>
点击按钮再发出JSONP跨域请求。
本质上是点击按钮的瞬间,创建了一个script标签,script标签的src指向了我们刚刚写的那个接口,那个接口是函数的调用。我们快速定义这个函数,使得src引入的js能够调用这个函数,从而通过实参和形参的结合,将数据传入页面。
<script>$("button").click(function(){//创建script标签var $o = $("<script><\/script>");//创建一个src$o.attr("src" , "http://127.0.0.88/a.php?callback=xixi");//定义全局函数window.xixi= function(data){//接收到数据的回调函数console.log(data);}//上树$("head").append($o); //下树 $o.remove();}); </script>
但实际上不用这么麻烦,jQuery会自动帮我们发出jsonp跨域:
<html lang="en"> <head><title>Document</title> </head> <body><button>按我发出请求</button><script>$("button").click(function(){$.ajax({"dataType" : "JSONP" ,"url" : "http://127.0.0.88/a.php","success" : function(data){console.log(data);}})});</script> </body> </html>
jQuery会随机生成一个函数名。
原理和我们写的一样的,都是:
1)瞬间创建一个内部函数
2)瞬间创建一个script标签,src指向我们的url地址
3)瞬间上树
4)瞬间下树
3.3跨域方法1:JSONP跨域
之前我们项目的数据和前端的文件都是同源的(就是在同一个接口下)。
但是,工作中,一定是要跨域请求数据的。
比如我们的前端项目运行在8080端口,要请求3000端口的数据,就是跨域。
事实上,工作中,模拟接口一定是不同ip的,模拟接口运行在办公室的局域网上的。
每个人的电脑都是同一个局域网的,后台哥哥会给你一个后端接口文档,接口在演示的时候,很有可能是3000、8000等等。但你的前端项目跑在webpack-dev-server的8080端口,就涉及到跨域请求数据了。
创建一个后端文件夹(server_side)和前端项目文件夹(Vue_study):
前端后端共同跑:后端3000,前端8080
app.js
var express = require("express"); var app = express();app.get("/a", function(req,res){// res.json({"a":100});res.jsonp({"a":100}); //jsonp()能自动得到callback参数请求 })app.listen(3000);
示例代码
http://127.0.0.1:3000/a?callback=haha
App.vue
<template><div><h1>首页</h1><button @click="addServer">请求数据</button></div> </template> <script> export default {methods:{addServer(){$.ajax({dataType:"JSONP",url: "http://127.0.0.1:3000/a",success:function(data){console.log(data)}})}} }; </script>
示例代码
3.4跨域方法2:CORS跨域
面试想要回答的好,看下面文章:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
http://www.ruanyifeng.com/blog/2016/04/cors.html
跨域资源共享(CORS,Cross-Origin Resource Sharing)机制允许Web应用服务器进行跨域访问控制,从而使得跨域数据传输得以安全进行。浏览器支持在API容器中(例如XMLHttpRequest或fetch)使用CORS,以降低跨域HTTP请求所带来的风险。
说白了,就是在HTTP下响应的头部加一句话。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
我们在后端一般就加Access-Control-Allow-Origin 值为“*”
问题:8080的前端页面请求3000后端的页面,是谁禁止的?是浏览器禁止的,为了安全。此时就要写一个HTTP下行响应头部,来告诉浏览器,这次请求是允许的,这是最简单的跨域方法,但是IE8才开始兼容。
app.js后端:
var express = require("express"); var app = express();app.get("/a", function(req,res){//表示允许任何域名来源的请求res.setHeader("Access-Control-Allow-Origin", "*");res.json({a:100}); })app.listen(3000);
App.vue此时在前端项目中就可以随意跨域:
<template><div><h1>首页</h1><button @click="addServer">请求数据</button></div> </template> <script> export default {methods:{addServer(){$.get("http://127.0.0.1:3000/a", function(data){console.log(data)})}} } </script>
示例代码
3.5跨域请求方法3:代理跨越(proxy)
“代理”就是偷数据。
拿PHP做例子,实现一下偷百度首页(了解即可)
<?phpecho file_get_contents("http://www.baidu.com/"); ?>
运行tou.php就直接是百度首页了。
比如京东充话费接口,可以被后端偷来:
然后在前端项目中使用:
<body><h1>手机归属地查询(业绩最快,完全免费)</h1><input type="text" id="tel"><button>查询</button> </body> <script type="text/javascript" src="js/jquery-2.2.4.min.js"></script> <script type="text/javascript">$("button").click(function(){var tel = $("#tel").val();//可以请求自己服务器的数据,只不过数据由后端tou.php偷回来。$.get("http://127.0.0.1:8088/tou.php?tel=" + tel, function(data){console.log(data)})}); </script>
示例代码
【重点】:如何在Vue和React项目中使用代理跨域?
webpack-dev-server可以帮我们偷服务端的数据,美其名曰“代理”。
相当于服务器去“偷数据”,由后端(前端的后端,就是webpack-dev-server)出面,问3000端口要数据
在webpack.config.js中,加几句话即可实现“代理跨域”。
https://webpack.docschina.org/configuration/dev-server/#devserver-proxy
webpack-dev-server这个小型服务器底层也是express实现的
webpack-dev-server在帮我们做几件事:
1)构建app文件夹到/public/all.js去
2)静态化www文件夹提供了静态文件的路由
3)代理了127.0.0.1:3000的接口。
4)构建app的时候进行了翻译
webpack.config.js配置:
var path = require('path'); const {VueLoaderPlugin} = require("vue-loader"); //最新版webpack需要引入此插件 module.exports = {//程序的入口文件entry: './www/app/app.js',//程序的出口文件(被打包的文件) output: {... },//自动监听watch:true,mode : "development",//配置webpack的模块插件 module:{// 关于模块配置 ...},resolve: {...}, devServer: {proxy: {'/api': {target: 'http://127.0.0.1:3000', //设置你调用的接口域名和端口//这里理解成/api代理target中的地址,后面组件中调用接口要使用/api代替pathRewrite: {'^/api' : ''}}}},//最新版webpack需要引入此插件 plugins:[new VueLoaderPlugin()] };
这些配置都从webpack官网抄的,配置就可以做项目了,实现接口的请求。
配置好后,重启 npm run dev,比如3000有一个接口/a,现在将被代理到8080接口的/api/a:
http://127.0.0.1:3000/a这个接口,被“代理”到http://127.0.0.1:8080/api/a
如果后端app.js出一个这样的接口:http://127.0.0.1/:3000/a
app.get("/a",function(req,res){res.json({"a":100});});
前端app.js就可以这样获取后端的接口:http://127.0.0.1/:8080/api/a
<template><div><h1>首页</h1><button @click="addServer">请求数据</button></div> </template> <script> export default {methods : {addServer(){ $.get("http://127.0.0.1:8080/api/a",function(data){console.log(data);})}} } </script>
总结:一提起“跨域”,立马回答他一共有三种方法。
四、练习代理跨域
后端app.js提供数据接口:(node app.js运行)
var express = require("express"); var app = express(); app.get("/a" , function(req,res){res.json({"a":100}); }); app.listen(3000);
示例代码
前端main.js
import Vue from "vue"; import Vuex from "vuex"; import App from "./App.vue"; import store from "./store";new Vue({el:"#app",store,render:(h)=>h(App) })
前端App.vue:
<template><div><h1>{{$store.state.counterState.a}}</h1><button @click="add(1)">加1</button><button @click="add(2)">加2</button><button @click="addServer">按我加服务器的数据</button></div> </template> <script>export default {methods : { add(n){this.$store.commit("ADD", {n}); },addServer(){//异步必须用dispatch this.$store.dispatch("ADDSERVER"); }}} </script>
store中的index.js:
import Vue from "vue"; import Vuex from "vuex"; import createLogger from 'vuex/dist/logger';import counterState from "./counter/state.js"; import counterMutations from "./counter/mutations.js"; import counterActions from "./counter/actions.js";Vue.use(Vuex); //全局数据 export default new Vuex.Store({ state: {counterState},//同步的(commit)mutations: {...counterMutations},//异步的(dispatch) actions : {...counterActions},plugins: [createLogger()] });
state.js
export default {a: 100 }
实例代码
mutations.js
export default { ADD(state, payload) {state.counterState.a += payload.n; } }
actions.js
export default {async ADDSERVER({commit}){//发出异步请求const {a} = await fetch("/api/a").then(data=>data.json());//异步函数不能改变state,改变state只有mutationscommit("ADD" , {n:a}) //触发mutation } }
转载于:https://www.cnblogs.com/rope/p/10737428.html
前端笔记之Vue(五)TodoList实战拆分store跨域练习代理跨域相关推荐
- 前端自检梳理——Vue.js项目实战开发
01. Vue基础语法 1)总结 2)总结 3)组件化开发 4) 02. Vue路由 目标 总结 03. Vue前端工程化 目标 总结 04. Vue电商项目实战 Day01目标 Day01总结 Da ...
- Web前端笔记-解决Vue编写的输入框(input、textarea等)使用JS设置value时提交表单无效的问题
主要的原因是vue相当于套了一层,界面上的输入框会关联model,提交表单的时候,他是直接提交model的值,而不是传统的输入框里面的值. 所以用这种: let textAreaItem = docu ...
- Android学习笔记(十五)——实战:强制下线
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 实现强制下线功能的思路也比较简单,只需要在界面上弹出一个对话框, 让用户无法进行任何其他操作, 必须要点击对话 ...
- Web前端笔记-安装vue的4.5.9版本
安装10版本以上的node 安装完后: node -v npm -v npm get registry npm config set registry http://registry.npm.taob ...
- 前端笔记-使用vue绑定id使得组件更加灵活(在使用echarts时常用)
目录 基本概念 代码与实例 基本概念 这个问题是在我使用echarts时出现的,因为echarts有这样的一个函数(官方实例) let myChart = this.$echarts.init(doc ...
- 零基础前端笔记(2)html,表格,列表,标签,文本域,表单域
XHTML可扩展超文本标记语言(2) (1)创建表格 (2)表格属性 表头单元格标签th 表格标题caption 小说排行榜 (3)合并单元格 (4)划分表格结构 (5)列表标签 无序列表 有序列表 ...
- 前端笔记知识点整合之JavaScript(五)关于数组和字符串那点事
前端笔记知识点整合之JavaScript(五)关于数组和字符串那点事 一.数组 1.1数组概念 数组(array)是一个有序的数据集合.说白了,数组就是一组数.数组内部可以存放一个或多个单独的数据,整 ...
- vue 动态添加class_前端开发:Vue项目实战-Music
大家好,我来了,本期为大家带来的前端开发知识是"前端开发:Vue项目实战-Music",有兴趣做前端的朋友,和我一起来看看吧! 主要内容 项目环境搭建 路由导航实现 ListVie ...
- vue 将字符串最后一个字符给替换_前端开发:Vue项目实战-Music
大家好,我来了,本期为大家带来的前端开发知识是"前端开发:Vue项目实战-Music",有兴趣做前端的朋友,和我一起来看看吧! 主要内容 项目环境搭建 路由导航实现 ListVie ...
- R语言实战笔记--第十五章 处理缺失数据
R语言实战笔记–第十五章 处理缺失数据 标签(空格分隔): R语言 处理缺失数据 VIM mice 缺失值(NA),是导致我们计算错误的一大来源,处理缺失数据在实际的应用中有着较为重要的作用. 基本方 ...
最新文章
- node、Mongo项目如何前后端分离提供接口给前端
- 第3关:递归实现二叉树左右子树交换
- sql语句,怎么查看一个表中的所有约束
- kill命令---Linux学习笔记
- 【完整版-斯坦福-密码学】全13讲(流密码)【笔记】
- cs中ComboBox以设置DataSource方式填充后,清除选项出错
- Lua实现二进制串与Hex显示串的相互转换
- java取整和java四舍五入方法
- Django基础(29): select_related和prefetch_related的用法与区别
- linux下chm阅读器
- Python 获取 网易云音乐热门评论
- 【转帖】年轻人不讲武德=白piao接口测试知识还白piao接口测试工具会员
- JavaBeans分类
- MFC中添加GIF图片
- supervisor的使用教程
- 个人支付宝/微信/云闪付/商户聚合码/银行卡等到账通知常用技术方案总结
- 理解你的排序操作(stable_sort,sort,partial_sort,nth_element,stable_partition,partition)
- 使用迅搜制作站内搜索引擎-安装篇
- 插入u盘需重启计算机,电脑一插u盘就重启的原因及其解决方案
- win10电脑显示 “您的账户已被停用。请向系统管理员咨询”,如何启动账号?
热门文章
- Linux下socket-文件传输
- (4)回归决策树_预测波士顿房价
- 社交网络图中结点的“重要性”计算 (30 分)(Floyd)
- linux c 宏 文件名,C语言标准宏获取文件名、行号、函数名的方法以及#和##的用法...
- java map的key和value_Java Map集合按照key和value排序之法
- JAVA程序将PDF转化为TXT
- jQuery学习笔记01
- 软件工程 第二章 可行性研究
- docker镜像打包
- 深度学习(二):传统神经网络